From 7e57f0a6a8fd4e5df7890613918f4a2c3b5a1fb7 Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Sun, 2 Sep 2018 22:26:38 -0700 Subject: [PATCH 0001/1984] Doc total order requirement of sort(_unstable)_by I took the definition of what a total order is from the Ord trait docs. I specifically put "elements of the slice" because if you have a slice of f64s, but know none are NaN, then sorting by partial ord is total in this case. I'm not sure if I should give such an example in the docs or not. --- src/liballoc/slice.rs | 7 +++++++ src/libcore/slice/mod.rs | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 33d28bef2d7..2ded376b395 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -211,6 +211,13 @@ impl [T] { /// /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. /// + /// The comparator function must define a total ordering for the elements in the slice. If + /// the ordering is not total, the order of the elements is unspecified. An order is a + /// total order if it is (for all a, b and c): + /// + /// * total and antisymmetric: exactly one of a < b, a == b or a > b is true; and + /// * transitive, a < b and b < c implies a < c. The same must hold for both == and >. + /// /// When applicable, unstable sorting is preferred because it is generally faster than stable /// sorting and it doesn't allocate auxiliary memory. /// See [`sort_unstable_by`](#method.sort_unstable_by). diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index a50426ba886..c22ea0a01f8 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1339,6 +1339,13 @@ impl [T] { /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), /// and `O(n log n)` worst-case. /// + /// The comparator function must define a total ordering for the elements in the slice. If + /// the ordering is not total, the order of the elements is unspecified. An order is a + /// total order if it is (for all a, b and c): + /// + /// * total and antisymmetric: exactly one of a < b, a == b or a > b is true; and + /// * transitive, a < b and b < c implies a < c. The same must hold for both == and >. + /// /// # Current implementation /// /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters, From e36bbc82f2fc49945b4ef42ddeca8c1443c3bac4 Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Mon, 3 Sep 2018 23:11:15 -0700 Subject: [PATCH 0002/1984] Example of total ord of elements for sort_by --- src/liballoc/slice.rs | 6 ++++++ src/libcore/slice/mod.rs | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 2ded376b395..ad47eb4b70b 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -242,6 +242,12 @@ impl [T] { /// // reverse sorting /// v.sort_by(|a, b| b.cmp(a)); /// assert!(v == [5, 4, 3, 2, 1]); + /// + /// // While f64 doesn't implement Ord because NaN != NaN, we can use + /// // partial_cmp here because we know none of the elements are NaN. + /// let mut floats = [5f64, 4.0, 1.0, 3.0, 2.0]; + /// floats.sort_by(|a, b| a.partial_cmp(b).unwrap()); + /// assert_eq!(floats, [1.0, 2.0, 3.0, 4.0, 5.0]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index c22ea0a01f8..a6e0389e66f 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1367,6 +1367,12 @@ impl [T] { /// // reverse sorting /// v.sort_unstable_by(|a, b| b.cmp(a)); /// assert!(v == [5, 4, 3, 2, 1]); + /// + /// // While f64 doesn't implement Ord because NaN != NaN, we can use + /// // partial_cmp here because we know none of the elements are NaN. + /// let mut floats = [5f64, 4.0, 1.0, 3.0, 2.0]; + /// floats.sort_unstable_by(|a, b| a.partial_cmp(b).unwrap()); + /// assert_eq!(floats, [1.0, 2.0, 3.0, 4.0, 5.0]); /// ``` /// /// [pdqsort]: https://github.com/orlp/pdqsort From b911dba40b441a65d8566e2013256612a15d27a4 Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Sun, 9 Sep 2018 22:07:17 -0700 Subject: [PATCH 0003/1984] Slice total example: Move closer to total defn --- src/liballoc/slice.rs | 15 +++++++++------ src/libcore/slice/mod.rs | 15 +++++++++------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index ad47eb4b70b..0802dc3e500 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -218,6 +218,15 @@ impl [T] { /// * total and antisymmetric: exactly one of a < b, a == b or a > b is true; and /// * transitive, a < b and b < c implies a < c. The same must hold for both == and >. /// + /// For example, while `f64` doesn't implement `Ord` because `NaN != NaN`, we can use + /// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`. + /// + /// ``` + /// let mut floats = [5f64, 4.0, 1.0, 3.0, 2.0]; + /// floats.sort_by(|a, b| a.partial_cmp(b).unwrap()); + /// assert_eq!(floats, [1.0, 2.0, 3.0, 4.0, 5.0]); + /// ``` + /// /// When applicable, unstable sorting is preferred because it is generally faster than stable /// sorting and it doesn't allocate auxiliary memory. /// See [`sort_unstable_by`](#method.sort_unstable_by). @@ -242,12 +251,6 @@ impl [T] { /// // reverse sorting /// v.sort_by(|a, b| b.cmp(a)); /// assert!(v == [5, 4, 3, 2, 1]); - /// - /// // While f64 doesn't implement Ord because NaN != NaN, we can use - /// // partial_cmp here because we know none of the elements are NaN. - /// let mut floats = [5f64, 4.0, 1.0, 3.0, 2.0]; - /// floats.sort_by(|a, b| a.partial_cmp(b).unwrap()); - /// assert_eq!(floats, [1.0, 2.0, 3.0, 4.0, 5.0]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index a6e0389e66f..f6695d876f8 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1346,6 +1346,15 @@ impl [T] { /// * total and antisymmetric: exactly one of a < b, a == b or a > b is true; and /// * transitive, a < b and b < c implies a < c. The same must hold for both == and >. /// + /// For example, while `f64` doesn't implement `Ord` because `NaN != NaN`, we can use + /// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`. + /// + /// ``` + /// let mut floats = [5f64, 4.0, 1.0, 3.0, 2.0]; + /// floats.sort_by(|a, b| a.partial_cmp(b).unwrap()); + /// assert_eq!(floats, [1.0, 2.0, 3.0, 4.0, 5.0]); + /// ``` + /// /// # Current implementation /// /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters, @@ -1367,12 +1376,6 @@ impl [T] { /// // reverse sorting /// v.sort_unstable_by(|a, b| b.cmp(a)); /// assert!(v == [5, 4, 3, 2, 1]); - /// - /// // While f64 doesn't implement Ord because NaN != NaN, we can use - /// // partial_cmp here because we know none of the elements are NaN. - /// let mut floats = [5f64, 4.0, 1.0, 3.0, 2.0]; - /// floats.sort_unstable_by(|a, b| a.partial_cmp(b).unwrap()); - /// assert_eq!(floats, [1.0, 2.0, 3.0, 4.0, 5.0]); /// ``` /// /// [pdqsort]: https://github.com/orlp/pdqsort From 99bed21101ef098393c9e6c8eb64f21892dbc8be Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Mon, 10 Sep 2018 15:38:37 -0700 Subject: [PATCH 0004/1984] Linkify types in docs --- src/liballoc/slice.rs | 2 +- src/libcore/slice/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 0802dc3e500..5f992795531 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -218,7 +218,7 @@ impl [T] { /// * total and antisymmetric: exactly one of a < b, a == b or a > b is true; and /// * transitive, a < b and b < c implies a < c. The same must hold for both == and >. /// - /// For example, while `f64` doesn't implement `Ord` because `NaN != NaN`, we can use + /// For example, while [`f64`] doesn't implement [`Ord`] because `NaN != NaN`, we can use /// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`. /// /// ``` diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index f6695d876f8..a9d76376c07 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1346,7 +1346,7 @@ impl [T] { /// * total and antisymmetric: exactly one of a < b, a == b or a > b is true; and /// * transitive, a < b and b < c implies a < c. The same must hold for both == and >. /// - /// For example, while `f64` doesn't implement `Ord` because `NaN != NaN`, we can use + /// For example, while [`f64`] doesn't implement [`Ord`] because `NaN != NaN`, we can use /// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`. /// /// ``` From 965a97093e727ddbbc12a99bf4b431b7843a841c Mon Sep 17 00:00:00 2001 From: eV Date: Sat, 13 Oct 2018 03:16:09 +0000 Subject: [PATCH 0005/1984] targets: thumbv8m: Add target for baseline ARMv8-M --- src/librustc_target/spec/mod.rs | 1 + src/librustc_target/spec/thumb_base.rs | 5 +-- .../spec/thumbv8m_none_eabi.rs | 33 +++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/librustc_target/spec/thumbv8m_none_eabi.rs diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 3f1e8ee5528..e7ea4a3d207 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -397,6 +397,7 @@ supported_targets! { ("thumbv7m-none-eabi", thumbv7m_none_eabi), ("thumbv7em-none-eabi", thumbv7em_none_eabi), ("thumbv7em-none-eabihf", thumbv7em_none_eabihf), + ("thumbv8m-none-eabi", thumbv8m_none_eabi), ("msp430-none-elf", msp430_none_elf), diff --git a/src/librustc_target/spec/thumb_base.rs b/src/librustc_target/spec/thumb_base.rs index 4c9a4764eff..795a1fbcf98 100644 --- a/src/librustc_target/spec/thumb_base.rs +++ b/src/librustc_target/spec/thumb_base.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// These 4 `thumbv*` targets cover the ARM Cortex-M family of processors which are widely used in +// These `thumbv*` targets cover the ARM Cortex-M family of processors which are widely used in // microcontrollers. Namely, all these processors: // // - Cortex-M0 @@ -17,8 +17,9 @@ // - Cortex-M3 // - Cortex-M4(F) // - Cortex-M7(F) +// - Cortex-M23 // -// We have opted for 4 targets instead of one target per processor (e.g. `cortex-m0`, `cortex-m3`, +// We have opted for these targets instead of one target per processor (e.g. `cortex-m0`, `cortex-m3`, // etc) because the differences between some processors like the cortex-m0 and cortex-m1 are almost // non-existent from the POV of codegen so it doesn't make sense to have separate targets for them. // And if differences exist between two processors under the same target, rustc flags can be used to diff --git a/src/librustc_target/spec/thumbv8m_none_eabi.rs b/src/librustc_target/spec/thumbv8m_none_eabi.rs new file mode 100644 index 00000000000..a0adeef2e04 --- /dev/null +++ b/src/librustc_target/spec/thumbv8m_none_eabi.rs @@ -0,0 +1,33 @@ +// Copyright 2018 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. + +// Targets the Cortex-M23 processor (Baseline ARMv8-M) + +use spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "thumbv8m.base-none-eabi".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + target_os: "none".to_string(), + target_env: String::new(), + target_vendor: String::new(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), + + options: TargetOptions { + max_atomic_width: Some(32), + .. super::thumb_base::opts() + }, + }) +} From 0e131052f6ba7765249c7401406b504899994b7b Mon Sep 17 00:00:00 2001 From: eV Date: Sat, 13 Oct 2018 15:52:40 +0000 Subject: [PATCH 0006/1984] fix tidy --- src/librustc_target/spec/thumb_base.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_target/spec/thumb_base.rs b/src/librustc_target/spec/thumb_base.rs index 795a1fbcf98..22e5f49fd59 100644 --- a/src/librustc_target/spec/thumb_base.rs +++ b/src/librustc_target/spec/thumb_base.rs @@ -19,7 +19,7 @@ // - Cortex-M7(F) // - Cortex-M23 // -// We have opted for these targets instead of one target per processor (e.g. `cortex-m0`, `cortex-m3`, +// We have opted for these instead of one target per processor (e.g. `cortex-m0`, `cortex-m3`, // etc) because the differences between some processors like the cortex-m0 and cortex-m1 are almost // non-existent from the POV of codegen so it doesn't make sense to have separate targets for them. // And if differences exist between two processors under the same target, rustc flags can be used to From 8a0666d5cc2def02e64b1090efc494d81a0b8dd1 Mon Sep 17 00:00:00 2001 From: eV Date: Fri, 19 Oct 2018 04:51:02 +0000 Subject: [PATCH 0007/1984] rename to thumbv8m.base-none-eabi, fix strict alignment --- src/librustc_target/spec/mod.rs | 2 +- .../spec/{thumbv8m_none_eabi.rs => thumbv8m_base_none_eabi.rs} | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) rename src/librustc_target/spec/{thumbv8m_none_eabi.rs => thumbv8m_base_none_eabi.rs} (87%) diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index e7ea4a3d207..7c8409becc1 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -397,7 +397,7 @@ supported_targets! { ("thumbv7m-none-eabi", thumbv7m_none_eabi), ("thumbv7em-none-eabi", thumbv7em_none_eabi), ("thumbv7em-none-eabihf", thumbv7em_none_eabihf), - ("thumbv8m-none-eabi", thumbv8m_none_eabi), + ("thumbv8m.base-none-eabi", thumbv8m_base_none_eabi), ("msp430-none-elf", msp430_none_elf), diff --git a/src/librustc_target/spec/thumbv8m_none_eabi.rs b/src/librustc_target/spec/thumbv8m_base_none_eabi.rs similarity index 87% rename from src/librustc_target/spec/thumbv8m_none_eabi.rs rename to src/librustc_target/spec/thumbv8m_base_none_eabi.rs index a0adeef2e04..b6143711563 100644 --- a/src/librustc_target/spec/thumbv8m_none_eabi.rs +++ b/src/librustc_target/spec/thumbv8m_base_none_eabi.rs @@ -26,6 +26,9 @@ pub fn target() -> TargetResult { linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), options: TargetOptions { + // ARMv8-M baseline doesn't support unaligned loads/stores so we disable them + // with +strict-align. + features: "+strict-align".to_string(), max_atomic_width: Some(32), .. super::thumb_base::opts() }, From 32d07cc2fc23e7cfa8b23a495e6667bcc7cf643a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 26 Oct 2018 16:23:02 +0200 Subject: [PATCH 0008/1984] bootstrap: be more explicit on what we collect into. NFC --- src/bootstrap/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index ba601249ea8..957ebd2540a 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -783,10 +783,10 @@ impl Build { fn cflags(&self, target: Interned, which: GitRepo) -> Vec { // Filter out -O and /O (the optimization flags) that we picked up from // cc-rs because the build scripts will determine that for themselves. - let mut base: Vec = self.cc[&target].args().iter() + let mut base = self.cc[&target].args().iter() .map(|s| s.to_string_lossy().into_owned()) .filter(|s| !s.starts_with("-O") && !s.starts_with("/O")) - .collect::>(); + .collect::>(); // If we're compiling on macOS then we add a few unconditional flags // indicating that we want libc++ (more filled out than libstdc++) and From b089e79562aff01cee9b6246f9352ffecef4b3b9 Mon Sep 17 00:00:00 2001 From: daniellimws Date: Mon, 29 Oct 2018 19:15:22 +0800 Subject: [PATCH 0009/1984] Add documentation for From impls --- src/liballoc/boxed.rs | 53 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index f989e701913..da4651ca779 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -438,6 +438,18 @@ impl Hasher for Box { #[stable(feature = "from_for_ptrs", since = "1.6.0")] impl From for Box { + /// Converts a generic type `T` into a `Box` + /// + /// The conversion allocates on the heap and moves `t` + /// from the stack into it. + /// + /// # Examples + /// ```rust + /// let x = 5; + /// let boxed = Box::new(5); + /// + /// assert_eq!(Box::from(x), boxed); + /// ``` fn from(t: T) -> Self { Box::new(t) } @@ -445,6 +457,9 @@ impl From for Box { #[unstable(feature = "pin", issue = "49150")] impl From> for Pin> { + /// Converts a `Box` into a `Pin>` + /// + /// This conversion does not allocate on the heap and happens in place. fn from(boxed: Box) -> Self { // It's not possible to move or replace the insides of a `Pin>` // when `T: !Unpin`, so it's safe to pin it directly without any @@ -455,6 +470,19 @@ impl From> for Pin> { #[stable(feature = "box_from_slice", since = "1.17.0")] impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { + /// Converts a `&[T]` into a `Box<[T]>` + /// + /// This conversion does not allocate on the heap + /// but performs a copy of `slice`. + /// + /// # Examples + /// ```rust + /// // create a &[u8] which will be used to create a Box<[u8]> + /// let slice: &[u8] = &[104, 101, 108, 108, 111]; + /// let boxed_slice = Box::from(slice); + /// + /// println!({:?}, boxed_slice); + /// ``` fn from(slice: &'a [T]) -> Box<[T]> { let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() }; boxed.copy_from_slice(slice); @@ -464,6 +492,15 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { #[stable(feature = "box_from_slice", since = "1.17.0")] impl<'a> From<&'a str> for Box { + /// Converts a `&str` into a `Box` + /// + /// This conversion does not allocate on the heap and happens in place. + /// + /// # Examples + /// ```rust + /// let boxed: Box = Box::from("hello"); + /// println!("{}", boxed); + /// ``` #[inline] fn from(s: &'a str) -> Box { unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) } @@ -472,6 +509,22 @@ impl<'a> From<&'a str> for Box { #[stable(feature = "boxed_str_conv", since = "1.19.0")] impl From> for Box<[u8]> { + /// Converts a `Box>` into a `Box<[u8]>` + /// + /// This conversion does not allocate on the heap and happens in place. + /// + /// # Examples + /// ```rust + /// // create a Box which will be used to create a Box<[u8]> + /// let boxed: Box = Box::from("hello"); + /// let boxed_str: Box<[u8]> = Box::from(boxed); + /// + /// // create a &[u8] which will be used to create a Box<[u8]> + /// let slice: &[u8] = &[104, 101, 108, 108, 111]; + /// let boxed_slice = Box::from(slice); + /// + /// assert_eq!(boxed_slice, boxed_str); + /// ``` #[inline] fn from(s: Box) -> Self { unsafe { Box::from_raw(Box::into_raw(s) as *mut [u8]) } From 15334e03b757c13578d15f49c5950eab21956437 Mon Sep 17 00:00:00 2001 From: daniellimws Date: Mon, 29 Oct 2018 19:37:58 +0800 Subject: [PATCH 0010/1984] Fix documentation for those that allocate on heap --- src/liballoc/boxed.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index da4651ca779..8826a836a91 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -472,8 +472,8 @@ impl From> for Pin> { impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { /// Converts a `&[T]` into a `Box<[T]>` /// - /// This conversion does not allocate on the heap - /// but performs a copy of `slice`. + /// This conversion allocates on the heap + /// and performs a copy of `slice`. /// /// # Examples /// ```rust @@ -494,7 +494,8 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { impl<'a> From<&'a str> for Box { /// Converts a `&str` into a `Box` /// - /// This conversion does not allocate on the heap and happens in place. + /// This conversion allocates on the heap + /// and performs a copy of `s`. /// /// # Examples /// ```rust From bc1885703cb46a462a4be1eea7c4e0f9abbe7a95 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 29 Oct 2018 14:44:15 -0400 Subject: [PATCH 0011/1984] Return &T / &mut T in ManuallyDrop Deref(Mut) impl Without this change the generated documentation looks like this: fn deref(&self) -> & as Deref>::Target Returning the actual type directly makes the generated docs more clear: fn deref(&self) -> &T --- src/libcore/mem.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 22016e8cf41..1f1df51919c 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -1018,7 +1018,7 @@ impl ManuallyDrop { impl Deref for ManuallyDrop { type Target = T; #[inline] - fn deref(&self) -> &Self::Target { + fn deref(&self) -> &T { &self.value } } @@ -1026,7 +1026,7 @@ impl Deref for ManuallyDrop { #[stable(feature = "manually_drop", since = "1.20.0")] impl DerefMut for ManuallyDrop { #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { + fn deref_mut(&mut self) -> &mut T { &mut self.value } } From 51fdc2bf1431d6ac1f32531f820a937ddbb70048 Mon Sep 17 00:00:00 2001 From: Florian Hartwig Date: Tue, 30 Oct 2018 23:27:05 +0100 Subject: [PATCH 0012/1984] Add example of using the indexing operator to HashMap docs --- src/libstd/collections/hash/map.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index ef5dae724b2..2bc440a19fb 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -318,6 +318,9 @@ const DISPLACEMENT_THRESHOLD: usize = 128; /// } /// } /// +/// // Look up the value for a key (will panic if the key is not found). +/// println!("Review for Jane: {}", book_reviews["Pride and Prejudice"]); +/// /// // Iterate over everything. /// for (book, review) in &book_reviews { /// println!("{}: \"{}\"", book, review); From 2d1cd9ae80f1c6f5c1925f52bd69344bf63610c7 Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Mon, 5 Nov 2018 17:23:34 +0000 Subject: [PATCH 0013/1984] Make `ParseIntError` and `IntErrorKind` fully public --- src/libcore/num/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index c6cbeea5a0e..fada8efbd21 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4768,11 +4768,11 @@ fn from_str_radix(src: &str, radix: u32) -> Result Date: Mon, 5 Nov 2018 21:22:45 +0000 Subject: [PATCH 0014/1984] Add useful attributes --- src/libcore/num/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index fada8efbd21..02c7689e2b6 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4771,7 +4771,10 @@ pub struct ParseIntError { pub kind: IntErrorKind, } +#[unstable(feature = "int_error_matching", + reason = "it can be useful to match errors when making error messages for integer parsing")] #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub enum IntErrorKind { Empty, InvalidDigit, From 420e6413c6124ba0c5032730af3ef50c7d2e2c95 Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Mon, 5 Nov 2018 21:37:10 +0000 Subject: [PATCH 0015/1984] break line to keep `travis_fold:start:tidy` happy --- src/libcore/num/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 02c7689e2b6..c218713823a 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4772,7 +4772,8 @@ pub struct ParseIntError { } #[unstable(feature = "int_error_matching", - reason = "it can be useful to match errors when making error messages for integer parsing")] + reason = "it can be useful to match errors when making error messages \ + for integer parsing")] #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub enum IntErrorKind { From b60efc1574fdba2504fdc903990a00893fd6d295 Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Mon, 5 Nov 2018 21:57:19 +0000 Subject: [PATCH 0016/1984] Continue to try to make travis happy by adding a issue number --- src/libcore/num/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index c218713823a..7657b45f024 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4773,7 +4773,8 @@ pub struct ParseIntError { #[unstable(feature = "int_error_matching", reason = "it can be useful to match errors when making error messages \ - for integer parsing")] + for integer parsing", + issue = "22639")] #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub enum IntErrorKind { From c3f0c9419e39a52758f99c156c41969341ff59da Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Tue, 6 Nov 2018 08:34:30 +0000 Subject: [PATCH 0017/1984] Add very useful documentation --- src/libcore/num/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 7657b45f024..b8f291f6d05 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4771,6 +4771,7 @@ pub struct ParseIntError { pub kind: IntErrorKind, } +/// Enum to store the various types of errors that can cause parsing an integer to fail. #[unstable(feature = "int_error_matching", reason = "it can be useful to match errors when making error messages \ for integer parsing", @@ -4778,9 +4779,16 @@ pub struct ParseIntError { #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub enum IntErrorKind { + /// Value being parsed is empty. + /// Among other causes, this variant will be constructed when parsing an empty string. Empty, + /// Contains an invalid digit. + /// Among other causes, this variant will be constructed when parsing a string that + /// contains a letter. InvalidDigit, + /// Integer is too small to store in target integer type. Overflow, + /// Integer is too large to store in target integer type. Underflow, } From 3dc56b7d9c81cdfb400cf6b937f12ee3b7e3b6b9 Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Tue, 6 Nov 2018 08:37:25 +0000 Subject: [PATCH 0018/1984] Fix mistake in my markdown --- src/libcore/num/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index b8f291f6d05..f31ce033649 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4780,9 +4780,11 @@ pub struct ParseIntError { #[non_exhaustive] pub enum IntErrorKind { /// Value being parsed is empty. + /// /// Among other causes, this variant will be constructed when parsing an empty string. Empty, /// Contains an invalid digit. + /// /// Among other causes, this variant will be constructed when parsing a string that /// contains a letter. InvalidDigit, From f1a593d1162dc399222c219a261bc95126e7fa62 Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Tue, 6 Nov 2018 09:29:24 +0000 Subject: [PATCH 0019/1984] Document kind field --- src/libcore/num/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index f31ce033649..a7b6d719c6a 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4768,6 +4768,7 @@ fn from_str_radix(src: &str, radix: u32) -> Result Date: Wed, 7 Nov 2018 08:35:28 +0000 Subject: [PATCH 0020/1984] Use method rather than public field --- src/libcore/num/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index a7b6d719c6a..e297050f1f0 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4768,8 +4768,7 @@ fn from_str_radix(src: &str, radix: u32) -> Result IntErrorKind { + self.kind + } #[unstable(feature = "int_error_internals", reason = "available through Error trait and this method should \ not be exposed publicly", From d0bac148f7ae149ea93b1610fd2398fc1f00da65 Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Wed, 7 Nov 2018 08:38:34 +0000 Subject: [PATCH 0021/1984] Fix incorrect documentation --- src/libcore/num/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index e297050f1f0..ad448af9af8 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4788,9 +4788,9 @@ pub enum IntErrorKind { /// Among other causes, this variant will be constructed when parsing a string that /// contains a letter. InvalidDigit, - /// Integer is too small to store in target integer type. - Overflow, /// Integer is too large to store in target integer type. + Overflow, + /// Integer is too small to store in target integer type. Underflow, } From 51e1f5560de3f9c8ae673c8014a5ed9547c1ce86 Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Wed, 7 Nov 2018 08:48:37 +0000 Subject: [PATCH 0022/1984] add unstable attribute --- src/libcore/num/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index ad448af9af8..71617347e4c 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4796,6 +4796,10 @@ pub enum IntErrorKind { impl ParseIntError { /// Outputs the detailed cause of parsing an integer failing. + #[unstable(feature = "int_error_matching", + reason = "it can be useful to match errors when making error messages \ + for integer parsing", + issue = "22639")] pub fn kind(self) -> IntErrorKind { self.kind } From b937be87cb89f08235a57e07e9c73b4489dc50a1 Mon Sep 17 00:00:00 2001 From: Meltinglava Date: Thu, 8 Nov 2018 15:33:10 +0100 Subject: [PATCH 0023/1984] Clarifying documentation for collections::hash_map::Entry::or_insert Previous version does not show that or_insert does not insert the passed value, as the passed value was the same value as what was already in the map. --- src/libstd/collections/hash/map.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 8de415e8aed..f84e03ae765 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -2030,7 +2030,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// /// assert_eq!(map["poneyland"], 12); /// - /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 12).1 += 10; + /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 += 10; /// assert_eq!(map["poneyland"], 22); /// ``` #[unstable(feature = "hash_raw_entry", issue = "54043")] @@ -2652,7 +2652,7 @@ impl<'a, K, V> Entry<'a, K, V> { /// /// assert_eq!(map["poneyland"], 12); /// - /// *map.entry("poneyland").or_insert(12) += 10; + /// *map.entry("poneyland").or_insert(10) += 10; /// assert_eq!(map["poneyland"], 22); /// ``` pub fn or_insert(self, default: V) -> &'a mut V { From 999c2e2433bb9bed2f30025e5bea4ca353293077 Mon Sep 17 00:00:00 2001 From: Daniel Alley Date: Fri, 9 Nov 2018 22:53:49 -0500 Subject: [PATCH 0024/1984] Fix #[cfg] for step impl on ranges --- src/libcore/iter/range.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 55addd86bc1..f0fd07b43ca 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -166,14 +166,14 @@ macro_rules! step_impl_no_between { } step_impl_unsigned!(usize u8 u16); -#[cfg(not(target_pointer_witdth = "16"))] +#[cfg(not(target_pointer_width = "16"))] step_impl_unsigned!(u32); -#[cfg(target_pointer_witdth = "16")] +#[cfg(target_pointer_width = "16")] step_impl_no_between!(u32); step_impl_signed!([isize: usize] [i8: u8] [i16: u16]); -#[cfg(not(target_pointer_witdth = "16"))] +#[cfg(not(target_pointer_width = "16"))] step_impl_signed!([i32: u32]); -#[cfg(target_pointer_witdth = "16")] +#[cfg(target_pointer_width = "16")] step_impl_no_between!(i32); #[cfg(target_pointer_width = "64")] step_impl_unsigned!(u64); From 8b750a77fc73290635499494779f77848a8e2b09 Mon Sep 17 00:00:00 2001 From: Meltinglava Date: Tue, 13 Nov 2018 12:20:23 +0100 Subject: [PATCH 0025/1984] The example values are now easyer to differenciate --- src/libstd/collections/hash/map.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index f84e03ae765..8ebf9b2fdf5 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -2026,12 +2026,12 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// use std::collections::HashMap; /// /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 12); /// - /// assert_eq!(map["poneyland"], 12); + /// map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 3); + /// assert_eq!(map["poneyland"], 3); /// - /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 += 10; - /// assert_eq!(map["poneyland"], 22); + /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 *= 2; + /// assert_eq!(map["poneyland"], 6); /// ``` #[unstable(feature = "hash_raw_entry", issue = "54043")] pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V) @@ -2648,12 +2648,12 @@ impl<'a, K, V> Entry<'a, K, V> { /// use std::collections::HashMap; /// /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(12); /// - /// assert_eq!(map["poneyland"], 12); + /// map.entry("poneyland").or_insert(3); + /// assert_eq!(map["poneyland"], 3); /// - /// *map.entry("poneyland").or_insert(10) += 10; - /// assert_eq!(map["poneyland"], 22); + /// *map.entry("poneyland").or_insert(10) *= 2; + /// assert_eq!(map["poneyland"], 6); /// ``` pub fn or_insert(self, default: V) -> &'a mut V { match self { From 008e5dcbd55cd751717ffd35a51dd65cd40011d4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 13 Nov 2018 13:42:05 -0800 Subject: [PATCH 0026/1984] appveyor: Use VS2017 for all our images This was [recommended by AppVeyor][1] to see if it has any impact on our build times, hopefully on the beneficial side of things! This shouldn't affect our binary compatibility for generated compilers like it would normally do for Linux. [1]: https://help.appveyor.com/discussions/questions/29832-did-recent-changes-apply-to-possibly-slow-down-builds#comment_46484879 --- appveyor.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 743e615c3f3..8cbb9c4e40a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,8 @@ environment: - SCCACHE_DIGEST: f808afabb4a4eb1d7112bcb3fa6be03b61e93412890c88e177c667eb37f46353d7ec294e559b16f9f4b5e894f2185fe7670a0df15fd064889ecbd80f0c34166c + # This is required for at least an AArch64 compiler in one image, and is + # otherwise recommended by AppVeyor currently for seeing if it has any + # affect on our job times. + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 Preview # By default schannel checks revocation of certificates unlike some other SSL # backends, but we've historically had problems on CI where a revocation @@ -82,7 +85,6 @@ environment: DIST_REQUIRE_ALL_TOOLS: 1 DEPLOY: 1 CI_JOB_NAME: dist-x86_64-msvc - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 Preview - RUST_CONFIGURE_ARGS: > --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc From a9a48ed3da1134364052322d628fd9d9418998f4 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 14 Nov 2018 16:22:14 -0700 Subject: [PATCH 0027/1984] Fix VecDeque pretty-printer This fixes the VecDeque pretty-printer to handle cases where head < tail. Closes #55944 --- src/etc/gdb_rust_pretty_printing.py | 14 +++++++++++--- src/test/debuginfo/pretty-std-collections.rs | 11 +++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index e6d5ef1a23f..27275ba3795 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -293,15 +293,23 @@ def display_hint(): def to_string(self): (tail, head, data_ptr, cap) = \ rustpp.extract_tail_head_ptr_and_cap_from_std_vecdeque(self.__val) + if head >= tail: + size = head - tail + else: + size = cap + head - tail return (self.__val.type.get_unqualified_type_name() + - ("(len: %i, cap: %i)" % (head - tail, cap))) + ("(len: %i, cap: %i)" % (size, cap))) def children(self): (tail, head, data_ptr, cap) = \ rustpp.extract_tail_head_ptr_and_cap_from_std_vecdeque(self.__val) gdb_ptr = data_ptr.get_wrapped_value() - for index in xrange(tail, head): - yield (str(index), (gdb_ptr + index).dereference()) + if head >= tail: + size = head - tail + else: + size = cap + head - tail + for index in xrange(0, size): + yield (str(index), (gdb_ptr + ((tail + index) % cap)).dereference()) class RustStdBTreeSetPrinter(object): diff --git a/src/test/debuginfo/pretty-std-collections.rs b/src/test/debuginfo/pretty-std-collections.rs index 8e37a884b34..0d3f4b90f23 100644 --- a/src/test/debuginfo/pretty-std-collections.rs +++ b/src/test/debuginfo/pretty-std-collections.rs @@ -28,6 +28,9 @@ // gdb-command: print vec_deque // gdb-check:$3 = VecDeque(len: 3, cap: 8) = {5, 3, 7} +// gdb-command: print vec_deque2 +// gdb-check:$4 = VecDeque(len: 7, cap: 8) = {2, 3, 4, 5, 6, 7, 8} + #![allow(unused_variables)] use std::collections::BTreeSet; use std::collections::BTreeMap; @@ -54,6 +57,14 @@ fn main() { vec_deque.push_back(3); vec_deque.push_back(7); + // VecDeque where an element was popped. + let mut vec_deque2 = VecDeque::new(); + for i in 1..8 { + vec_deque2.push_back(i) + } + vec_deque2.pop_front(); + vec_deque2.push_back(8); + zzz(); // #break } From 052bdff8fbaef9b3c32eec842fc9c03877651cf5 Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 15 Nov 2018 16:35:23 +0800 Subject: [PATCH 0028/1984] lint based on closure pipe span --- src/librustc/traits/error_reporting.rs | 16 +++++++++++++++- .../ui/mismatched_types/closure-arg-count.rs | 2 ++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 2761a954cea..d08a4b47b31 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1092,13 +1092,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Some(found_span) = found_span { err.span_label(found_span, format!("takes {}", found_str)); + // move |_| { ... } + // ^^^^^^^^-- def_span + // + // move |_| { ... } + // ^^^^^-- prefix + let prefix_span = self.tcx.sess.source_map().span_until_char(found_span, '|'); + // move |_| { ... } + // ^^^-- pipe_span + let pipe_span = if let Some(span) = found_span.trim_start(prefix_span) { + span + } else { + found_span + }; + // Suggest to take and ignore the arguments with expected_args_length `_`s if // found arguments is empty (assume the user just wants to ignore args in this case). // For example, if `expected_args_length` is 2, suggest `|_, _|`. if found_args.is_empty() && is_closure { let underscores = vec!["_"; expected_args.len()].join(", "); err.span_suggestion_with_applicability( - found_span, + pipe_span, &format!( "consider changing the closure to take and ignore the expected argument{}", if expected_args.len() < 2 { diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs index 9eb11148a8b..ed9162d2348 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.rs +++ b/src/test/ui/mismatched_types/closure-arg-count.rs @@ -22,6 +22,8 @@ fn main() { //~^ ERROR closure is expected to take f(|| panic!()); //~^ ERROR closure is expected to take + f(move || panic!()); + //~^ ERROR closure is expected to take let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i); //~^ ERROR closure is expected to take From dbd9abd74d1ca8329f483c30ba04526d8c45a5ac Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 15 Nov 2018 22:17:49 +0800 Subject: [PATCH 0029/1984] update closure arg suggesstion ui test --- .../mismatched_types/closure-arg-count.stderr | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 057cf6efa1d..89977aadf88 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -60,8 +60,26 @@ help: consider changing the closure to take and ignore the expected argument LL | f(|_| panic!()); | ^^^ +error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments + --> $DIR/closure-arg-count.rs:25:5 + | +LL | f(move || panic!()); + | ^ ------- takes 0 arguments + | | + | expected closure that takes 1 argument + | +note: required by `f` + --> $DIR/closure-arg-count.rs:13:1 + | +LL | fn f>(_: F) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider changing the closure to take and ignore the expected argument + | +LL | f(move|_| panic!()); + | ^^^ + error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments - --> $DIR/closure-arg-count.rs:26:53 + --> $DIR/closure-arg-count.rs:28:53 | LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i); | ^^^ ------ takes 2 distinct arguments @@ -73,7 +91,7 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i); | ^^^^^^^^ error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments - --> $DIR/closure-arg-count.rs:28:53 + --> $DIR/closure-arg-count.rs:30:53 | LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i); | ^^^ ------------- takes 2 distinct arguments @@ -85,7 +103,7 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i); | ^^^^^^^^ error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments - --> $DIR/closure-arg-count.rs:30:53 + --> $DIR/closure-arg-count.rs:32:53 | LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i); | ^^^ --------- takes 3 distinct arguments @@ -93,7 +111,7 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i); | expected closure that takes a single 2-tuple as argument error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 0 arguments - --> $DIR/closure-arg-count.rs:32:53 + --> $DIR/closure-arg-count.rs:34:53 | LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo); | ^^^ expected function that takes a single 2-tuple as argument @@ -102,7 +120,7 @@ LL | fn foo() {} | -------- takes 0 arguments error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments - --> $DIR/closure-arg-count.rs:35:53 + --> $DIR/closure-arg-count.rs:37:53 | LL | let bar = |i, x, y| i; | --------- takes 3 distinct arguments @@ -110,7 +128,7 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(bar); | ^^^ expected closure that takes a single 2-tuple as argument error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments - --> $DIR/closure-arg-count.rs:37:53 + --> $DIR/closure-arg-count.rs:39:53 | LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(qux); | ^^^ expected function that takes a single 2-tuple as argument @@ -119,13 +137,13 @@ LL | fn qux(x: usize, y: usize) {} | -------------------------- takes 2 distinct arguments error[E0593]: function is expected to take 1 argument, but it takes 2 arguments - --> $DIR/closure-arg-count.rs:40:41 + --> $DIR/closure-arg-count.rs:42:41 | LL | let _it = vec![1, 2, 3].into_iter().map(usize::checked_add); | ^^^ expected function that takes 1 argument error[E0593]: function is expected to take 0 arguments, but it takes 1 argument - --> $DIR/closure-arg-count.rs:43:5 + --> $DIR/closure-arg-count.rs:45:5 | LL | call(Foo); | ^^^^ expected function that takes 0 arguments @@ -134,11 +152,11 @@ LL | struct Foo(u8); | --------------- takes 1 argument | note: required by `call` - --> $DIR/closure-arg-count.rs:50:1 + --> $DIR/closure-arg-count.rs:52:1 | LL | fn call(_: F) where F: FnOnce() -> R {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 13 previous errors +error: aborting due to 14 previous errors For more information about this error, try `rustc --explain E0593`. From 6d40b7232eaa00ab5c060582011f350725703a1e Mon Sep 17 00:00:00 2001 From: Sebastian Geisler Date: Tue, 30 Oct 2018 22:24:33 -0700 Subject: [PATCH 0030/1984] Implement checked_add_duration for SystemTime Since SystemTime is opaque there is no way to check if the result of an addition will be in bounds. That makes the Add trait completely unusable with untrusted data. This is a big problem because adding a Duration to UNIX_EPOCH is the standard way of constructing a SystemTime from a unix timestamp. This commit implements checked_add_duration(&self, &Duration) -> Option for std::time::SystemTime and as a prerequisite also for all platform specific time structs. This also led to the refactoring of many add_duration(&self, &Duration) -> SystemTime functions to avoid redundancy (they now unwrap the result of checked_add_duration). Some basic unit tests for the newly introduced function were added too. --- src/libstd/sys/cloudabi/time.rs | 19 +++++++++++++------ src/libstd/sys/redox/time.rs | 25 +++++++++++++++++++------ src/libstd/sys/unix/time.rs | 29 +++++++++++++++++++++++------ src/libstd/sys/wasm/time.rs | 4 ++++ src/libstd/sys/windows/time.rs | 16 ++++++++++++---- src/libstd/time.rs | 21 +++++++++++++++++++++ 6 files changed, 92 insertions(+), 22 deletions(-) diff --git a/src/libstd/sys/cloudabi/time.rs b/src/libstd/sys/cloudabi/time.rs index ee12731619a..191324e26a4 100644 --- a/src/libstd/sys/cloudabi/time.rs +++ b/src/libstd/sys/cloudabi/time.rs @@ -19,10 +19,14 @@ pub struct Instant { t: abi::timestamp, } -pub fn dur2intervals(dur: &Duration) -> abi::timestamp { +fn checked_dur2intervals(dur: &Duration) -> Option { dur.as_secs() .checked_mul(NSEC_PER_SEC) .and_then(|nanos| nanos.checked_add(dur.subsec_nanos() as abi::timestamp)) +} + +pub fn dur2intervals(dur: &Duration) -> abi::timestamp { + checked_dur2intervals(dur) .expect("overflow converting duration to nanoseconds") } @@ -92,11 +96,14 @@ impl SystemTime { } pub fn add_duration(&self, other: &Duration) -> SystemTime { - SystemTime { - t: self.t - .checked_add(dur2intervals(other)) - .expect("overflow when adding duration to instant"), - } + self.checked_add_duration(other) + .expect("overflow when adding duration to instant") + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option { + checked_dur2intervals(other) + .and_then(|d| self.t.checked_add(d)) + .map(|t| SystemTime {t}) } pub fn sub_duration(&self, other: &Duration) -> SystemTime { diff --git a/src/libstd/sys/redox/time.rs b/src/libstd/sys/redox/time.rs index 5c491115c55..5f8799489aa 100644 --- a/src/libstd/sys/redox/time.rs +++ b/src/libstd/sys/redox/time.rs @@ -42,27 +42,36 @@ impl Timespec { } fn add_duration(&self, other: &Duration) -> Timespec { - let mut secs = other + self.checked_add_duration(other).expect("overflow when adding duration to time") + } + + fn checked_add_duration(&self, other: &Duration) -> Option { + let mut secs = match other .as_secs() .try_into() // <- target type would be `i64` .ok() .and_then(|secs| self.t.tv_sec.checked_add(secs)) - .expect("overflow when adding duration to time"); + { + Some(ts) => ts, + None => return None, + }; // Nano calculations can't overflow because nanos are <1B which fit // in a u32. let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; if nsec >= NSEC_PER_SEC as u32 { nsec -= NSEC_PER_SEC as u32; - secs = secs.checked_add(1).expect("overflow when adding \ - duration to time"); + secs = match secs.checked_add(1) { + Some(ts) => ts, + None => return None, + } } - Timespec { + Some(Timespec { t: syscall::TimeSpec { tv_sec: secs, tv_nsec: nsec as i32, }, - } + }) } fn sub_duration(&self, other: &Duration) -> Timespec { @@ -180,6 +189,10 @@ impl SystemTime { SystemTime { t: self.t.add_duration(other) } } + pub fn checked_add_duration(&self, other: &Duration) -> Option { + self.t.checked_add_duration(other).map(|t| SystemTime { t }) + } + pub fn sub_duration(&self, other: &Duration) -> SystemTime { SystemTime { t: self.t.sub_duration(other) } } diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index 0b1fb726357..50c3c00382e 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -43,27 +43,36 @@ impl Timespec { } fn add_duration(&self, other: &Duration) -> Timespec { - let mut secs = other + self.checked_add_duration(other).expect("overflow when adding duration to time") + } + + fn checked_add_duration(&self, other: &Duration) -> Option { + let mut secs = match other .as_secs() .try_into() // <- target type would be `libc::time_t` .ok() .and_then(|secs| self.t.tv_sec.checked_add(secs)) - .expect("overflow when adding duration to time"); + { + Some(ts) => ts, + None => return None, + }; // Nano calculations can't overflow because nanos are <1B which fit // in a u32. let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; if nsec >= NSEC_PER_SEC as u32 { nsec -= NSEC_PER_SEC as u32; - secs = secs.checked_add(1).expect("overflow when adding \ - duration to time"); + secs = match secs.checked_add(1) { + Some(ts) => ts, + None => return None, + } } - Timespec { + Some(Timespec { t: libc::timespec { tv_sec: secs, tv_nsec: nsec as _, }, - } + }) } fn sub_duration(&self, other: &Duration) -> Timespec { @@ -201,6 +210,10 @@ mod inner { SystemTime { t: self.t.add_duration(other) } } + pub fn checked_add_duration(&self, other: &Duration) -> Option { + self.t.checked_add_duration(other).map(|t| SystemTime { t }) + } + pub fn sub_duration(&self, other: &Duration) -> SystemTime { SystemTime { t: self.t.sub_duration(other) } } @@ -325,6 +338,10 @@ mod inner { SystemTime { t: self.t.add_duration(other) } } + pub fn checked_add_duration(&self, other: &Duration) -> Option { + self.t.checked_add_duration(other).map(|t| SystemTime { t }) + } + pub fn sub_duration(&self, other: &Duration) -> SystemTime { SystemTime { t: self.t.sub_duration(other) } } diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/wasm/time.rs index e52435e6339..991e8176edf 100644 --- a/src/libstd/sys/wasm/time.rs +++ b/src/libstd/sys/wasm/time.rs @@ -51,6 +51,10 @@ impl SystemTime { SystemTime(self.0 + *other) } + pub fn checked_add_duration(&self, other: &Duration) -> Option { + self.0.checked_add(*other).map(|d| SystemTime(d)) + } + pub fn sub_duration(&self, other: &Duration) -> SystemTime { SystemTime(self.0 - *other) } diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs index 07e64d386a1..8eebe4a85fe 100644 --- a/src/libstd/sys/windows/time.rs +++ b/src/libstd/sys/windows/time.rs @@ -128,9 +128,13 @@ impl SystemTime { } pub fn add_duration(&self, other: &Duration) -> SystemTime { - let intervals = self.intervals().checked_add(dur2intervals(other)) - .expect("overflow when adding duration to time"); - SystemTime::from_intervals(intervals) + self.checked_add_duration(other).expect("overflow when adding duration to time") + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option { + checked_dur2intervals(other) + .and_then(|d| self.intervals().checked_add(d)) + .map(|i| SystemTime::from_intervals(i)) } pub fn sub_duration(&self, other: &Duration) -> SystemTime { @@ -180,11 +184,15 @@ impl Hash for SystemTime { } } -fn dur2intervals(d: &Duration) -> i64 { +fn checked_dur2intervals(d: &Duration) -> Option { d.as_secs() .checked_mul(INTERVALS_PER_SEC) .and_then(|i| i.checked_add(d.subsec_nanos() as u64 / 100)) .and_then(|i| i.try_into().ok()) +} + +fn dur2intervals(d: &Duration) -> i64 { + checked_dur2intervals(d) .expect("overflow when converting duration to intervals") } diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 90ab3491599..94875d8993d 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -357,6 +357,14 @@ impl SystemTime { pub fn elapsed(&self) -> Result { SystemTime::now().duration_since(*self) } + + /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as + /// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None` + /// otherwise. + #[stable(feature = "time_checked_add", since = "1.32.0")] + pub fn checked_add_duration(&self, duration: &Duration) -> Option { + self.0.checked_add_duration(duration).map(|t| SystemTime(t)) + } } #[stable(feature = "time2", since = "1.8.0")] @@ -557,6 +565,19 @@ mod tests { let one_second_from_epoch2 = UNIX_EPOCH + Duration::new(0, 500_000_000) + Duration::new(0, 500_000_000); assert_eq!(one_second_from_epoch, one_second_from_epoch2); + + // checked_add_duration will not panic on overflow + let mut maybe_t = Some(SystemTime::UNIX_EPOCH); + let max_duration = Duration::from_secs(u64::max_value()); + // in case `SystemTime` can store `>= UNIX_EPOCH + max_duration`. + for _ in 0..2 { + maybe_t = maybe_t.and_then(|t| t.checked_add_duration(&max_duration)); + } + assert_eq!(maybe_t, None); + + // checked_add_duration calculates the right time and will work for another year + let year = Duration::from_secs(60 * 60 * 24 * 365); + assert_eq!(a + year, a.checked_add_duration(&year).unwrap()); } #[test] From 86ef38b3b7a24959ca11a29c79cf921ed5986bc9 Mon Sep 17 00:00:00 2001 From: Sebastian Geisler Date: Sun, 4 Nov 2018 21:23:20 -0800 Subject: [PATCH 0031/1984] Rename checked_add_duration to checked_add and make it take the duration by value --- src/libstd/time.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 94875d8993d..c905af442de 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -361,9 +361,9 @@ impl SystemTime { /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as /// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None` /// otherwise. - #[stable(feature = "time_checked_add", since = "1.32.0")] - pub fn checked_add_duration(&self, duration: &Duration) -> Option { - self.0.checked_add_duration(duration).map(|t| SystemTime(t)) + #[unstable(feature = "time_checked_add", issue = "55940")] + pub fn checked_add(&self, duration: Duration) -> Option { + self.0.checked_add_duration(&duration).map(|t| SystemTime(t)) } } @@ -571,13 +571,13 @@ mod tests { let max_duration = Duration::from_secs(u64::max_value()); // in case `SystemTime` can store `>= UNIX_EPOCH + max_duration`. for _ in 0..2 { - maybe_t = maybe_t.and_then(|t| t.checked_add_duration(&max_duration)); + maybe_t = maybe_t.and_then(|t| t.checked_add(max_duration)); } assert_eq!(maybe_t, None); // checked_add_duration calculates the right time and will work for another year let year = Duration::from_secs(60 * 60 * 24 * 365); - assert_eq!(a + year, a.checked_add_duration(&year).unwrap()); + assert_eq!(a + year, a.checked_add(year).unwrap()); } #[test] From f2106d0746cdbd04ddad44c35b4e13eeced2a546 Mon Sep 17 00:00:00 2001 From: Sebastian Geisler Date: Thu, 15 Nov 2018 22:56:07 -0800 Subject: [PATCH 0032/1984] use ? operator instead of match --- src/libstd/sys/redox/time.rs | 13 +++---------- src/libstd/sys/unix/time.rs | 13 +++---------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/src/libstd/sys/redox/time.rs b/src/libstd/sys/redox/time.rs index 5f8799489aa..514629282ac 100644 --- a/src/libstd/sys/redox/time.rs +++ b/src/libstd/sys/redox/time.rs @@ -46,25 +46,18 @@ impl Timespec { } fn checked_add_duration(&self, other: &Duration) -> Option { - let mut secs = match other + let mut secs = other .as_secs() .try_into() // <- target type would be `i64` .ok() - .and_then(|secs| self.t.tv_sec.checked_add(secs)) - { - Some(ts) => ts, - None => return None, - }; + .and_then(|secs| self.t.tv_sec.checked_add(secs))?; // Nano calculations can't overflow because nanos are <1B which fit // in a u32. let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; if nsec >= NSEC_PER_SEC as u32 { nsec -= NSEC_PER_SEC as u32; - secs = match secs.checked_add(1) { - Some(ts) => ts, - None => return None, - } + secs = secs.checked_add(1)?; } Some(Timespec { t: syscall::TimeSpec { diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index 50c3c00382e..6c7ee3dd922 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -47,25 +47,18 @@ impl Timespec { } fn checked_add_duration(&self, other: &Duration) -> Option { - let mut secs = match other + let mut secs = other .as_secs() .try_into() // <- target type would be `libc::time_t` .ok() - .and_then(|secs| self.t.tv_sec.checked_add(secs)) - { - Some(ts) => ts, - None => return None, - }; + .and_then(|secs| self.t.tv_sec.checked_add(secs))?; // Nano calculations can't overflow because nanos are <1B which fit // in a u32. let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; if nsec >= NSEC_PER_SEC as u32 { nsec -= NSEC_PER_SEC as u32; - secs = match secs.checked_add(1) { - Some(ts) => ts, - None => return None, - } + secs = secs.checked_add(1)?; } Some(Timespec { t: libc::timespec { From 65e6fdb92e8b706a944bd02bc01058857f787667 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 16 Nov 2018 11:59:31 +0100 Subject: [PATCH 0033/1984] Ensure that the `static_assert!` argument is a `bool` --- src/librustc_data_structures/macros.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_data_structures/macros.rs b/src/librustc_data_structures/macros.rs index 3cc91b0e93f..286a374b280 100644 --- a/src/librustc_data_structures/macros.rs +++ b/src/librustc_data_structures/macros.rs @@ -11,11 +11,12 @@ /// A simple static assertion macro. The first argument should be a unique /// ALL_CAPS identifier that describes the condition. #[macro_export] +#[allow_internal_unstable] macro_rules! static_assert { ($name:ident: $test:expr) => { // Use the bool to access an array such that if the bool is false, the access // is out-of-bounds. #[allow(dead_code)] - static $name: () = [()][!$test as usize]; + static $name: () = [()][!($test: bool) as usize]; } } From 7cb068e52368e374f1f2c41e98f4b802d3869d14 Mon Sep 17 00:00:00 2001 From: Axary Date: Fri, 16 Nov 2018 13:08:58 +0100 Subject: [PATCH 0034/1984] add ui test --- src/test/ui/bare-function-self.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/test/ui/bare-function-self.rs diff --git a/src/test/ui/bare-function-self.rs b/src/test/ui/bare-function-self.rs new file mode 100644 index 00000000000..5cd33da923c --- /dev/null +++ b/src/test/ui/bare-function-self.rs @@ -0,0 +1,15 @@ +// Copyright 2018 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. + + +fn a(&self) { } +//~^ ERROR `self` argument in bare function + +fn main() { } \ No newline at end of file From 80c2101b2042ba9ba3e4c7b2351ec45867965338 Mon Sep 17 00:00:00 2001 From: Axary Date: Fri, 16 Nov 2018 13:54:09 +0100 Subject: [PATCH 0035/1984] change expected error message --- src/test/ui/bare-function-self.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/bare-function-self.rs b/src/test/ui/bare-function-self.rs index 5cd33da923c..01189ae321b 100644 --- a/src/test/ui/bare-function-self.rs +++ b/src/test/ui/bare-function-self.rs @@ -10,6 +10,6 @@ fn a(&self) { } -//~^ ERROR `self` argument in bare function +//~^ ERROR unexpected `self` argument in bare function -fn main() { } \ No newline at end of file +fn main() { } From 218e35efa1500be4ebc1ee5d84a4e6971352c500 Mon Sep 17 00:00:00 2001 From: Axary Date: Fri, 16 Nov 2018 13:54:49 +0100 Subject: [PATCH 0036/1984] eat CloseDelim --- src/libsyntax/parse/parser.rs | 11 +++++++++-- src/test/ui/bare-function-self.stderr | 8 ++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/bare-function-self.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d90ec4ea081..dd1864ce124 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5385,11 +5385,16 @@ impl<'a> Parser<'a> { fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool) -> PResult<'a, (Vec , bool)> { + self.expect(&token::OpenDelim(token::Paren))?; + + if let Ok(Some(_)) = self.parse_self_arg() { + return Err(self.fatal("unexpected `self` argument in bare function")) + } + let sp = self.span; let mut variadic = false; let args: Vec> = - self.parse_unspanned_seq( - &token::OpenDelim(token::Paren), + self.parse_seq_to_before_end( &token::CloseDelim(token::Paren), SeqSep::trailing_allowed(token::Comma), |p| { @@ -5436,6 +5441,8 @@ impl<'a> Parser<'a> { } )?; + self.eat(&token::CloseDelim(token::Paren)); + let args: Vec<_> = args.into_iter().filter_map(|x| x).collect(); if variadic && args.is_empty() { diff --git a/src/test/ui/bare-function-self.stderr b/src/test/ui/bare-function-self.stderr new file mode 100644 index 00000000000..51db0ddd70d --- /dev/null +++ b/src/test/ui/bare-function-self.stderr @@ -0,0 +1,8 @@ +error: unexpected `self` argument in bare function + --> $DIR/bare-function-self.rs:12:11 + | +LL | fn a(&self) { } + | ^ + +error: aborting due to previous error + From 675319e5586817143fef60243d319395ae858ad1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 26 Oct 2018 00:55:12 +0200 Subject: [PATCH 0037/1984] lint if a private item has doctests --- src/librustc/lint/builtin.rs | 7 +++ src/librustdoc/core.rs | 4 +- .../passes/collect_intra_doc_links.rs | 45 ++------------ src/librustdoc/passes/mod.rs | 60 ++++++++++++++++++- .../passes/private_items_doc_tests.rs | 49 +++++++++++++++ src/test/rustdoc-ui/private-item-doc-test.rs | 20 +++++++ .../rustdoc-ui/private-item-doc-test.stderr | 16 +++++ 7 files changed, 158 insertions(+), 43 deletions(-) create mode 100644 src/librustdoc/passes/private_items_doc_tests.rs create mode 100644 src/test/rustdoc-ui/private-item-doc-test.rs create mode 100644 src/test/rustdoc-ui/private-item-doc-test.stderr diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 01d87bdbf63..22f2023eefb 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -318,6 +318,12 @@ declare_lint! { "warn about missing code example in an item's documentation" } +declare_lint! { + pub PRIVATE_DOC_TESTS, + Allow, + "warn about doc test in private item" +} + declare_lint! { pub WHERE_CLAUSES_OBJECT_SAFETY, Warn, @@ -415,6 +421,7 @@ impl LintPass for HardwiredLints { DUPLICATE_MACRO_EXPORTS, INTRA_DOC_LINK_RESOLUTION_FAILURE, MISSING_DOC_CODE_EXAMPLES, + PRIVATE_DOC_TESTS, WHERE_CLAUSES_OBJECT_SAFETY, PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, MACRO_USE_EXTERN_CRATE, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 0bd6f6bf8a2..aac0f9f94e3 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -351,13 +351,15 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let warnings_lint_name = lint::builtin::WARNINGS.name; let missing_docs = rustc_lint::builtin::MISSING_DOCS.name; let missing_doc_example = rustc_lint::builtin::MISSING_DOC_CODE_EXAMPLES.name; + let private_doc_tests = rustc_lint::builtin::PRIVATE_DOC_TESTS.name; // In addition to those specific lints, we also need to whitelist those given through // command line, otherwise they'll get ignored and we don't want that. let mut whitelisted_lints = vec![warnings_lint_name.to_owned(), intra_link_resolution_failure_name.to_owned(), missing_docs.to_owned(), - missing_doc_example.to_owned()]; + missing_doc_example.to_owned(), + private_doc_tests.to_owned()]; whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned()); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 471ba6345e2..675e3e9be1e 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -24,9 +24,9 @@ use std::ops::Range; use core::DocContext; use fold::DocFolder; -use html::markdown::{find_testable_code, markdown_links, ErrorCodes, LangString}; +use html::markdown::markdown_links; -use passes::Pass; +use passes::{look_for_tests, Pass}; pub const COLLECT_INTRA_DOC_LINKS: Pass = Pass::early("collect-intra-doc-links", collect_intra_doc_links, @@ -214,43 +214,6 @@ impl<'a, 'tcx, 'rcx, 'cstore> LinkCollector<'a, 'tcx, 'rcx, 'cstore> { } } -fn look_for_tests<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx>( - cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>, - dox: &str, - item: &Item, -) { - if (item.is_mod() && cx.tcx.hir.as_local_node_id(item.def_id).is_none()) || - cx.as_local_node_id(item.def_id).is_none() { - // If non-local, no need to check anything. - return; - } - - struct Tests { - found_tests: usize, - } - - impl ::test::Tester for Tests { - fn add_test(&mut self, _: String, _: LangString, _: usize) { - self.found_tests += 1; - } - } - - let mut tests = Tests { - found_tests: 0, - }; - - if find_testable_code(&dox, &mut tests, ErrorCodes::No).is_ok() { - if tests.found_tests == 0 { - let mut diag = cx.tcx.struct_span_lint_node( - lint::builtin::MISSING_DOC_CODE_EXAMPLES, - NodeId::from_u32(0), - span_of_attrs(&item.attrs), - "Missing code example in this documentation"); - diag.emit(); - } - } -} - impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for LinkCollector<'a, 'tcx, 'rcx, 'cstore> { fn fold_item(&mut self, mut item: Item) -> Option { let item_node_id = if item.is_mod() { @@ -313,7 +276,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for LinkCollector<'a, 'tcx, 'rcx, 'cstor let cx = self.cx; let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new); - look_for_tests(&cx, &dox, &item); + look_for_tests(&cx, &dox, &item, true); if !self.is_nightly_build { return None; @@ -488,7 +451,7 @@ fn macro_resolve(cx: &DocContext, path_str: &str) -> Option { None } -fn span_of_attrs(attrs: &Attributes) -> syntax_pos::Span { +pub fn span_of_attrs(attrs: &Attributes) -> syntax_pos::Span { if attrs.doc_strings.is_empty() { return DUMMY_SP; } diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index d00eb3257d4..eee7278e4f0 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -12,16 +12,22 @@ //! process. use rustc::hir::def_id::DefId; +use rustc::lint as lint; use rustc::middle::privacy::AccessLevels; use rustc::util::nodemap::DefIdSet; use std::mem; use std::fmt; +use syntax::ast::NodeId; use clean::{self, GetDefId, Item}; -use core::DocContext; +use core::{DocContext, DocAccessLevels}; use fold; use fold::StripItem; +use html::markdown::{find_testable_code, ErrorCodes, LangString}; + +use self::collect_intra_doc_links::span_of_attrs; + mod collapse_docs; pub use self::collapse_docs::COLLAPSE_DOCS; @@ -43,6 +49,9 @@ pub use self::propagate_doc_cfg::PROPAGATE_DOC_CFG; mod collect_intra_doc_links; pub use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS; +mod private_items_doc_tests; +pub use self::private_items_doc_tests::CHECK_PRIVATE_ITEMS_DOC_TESTS; + mod collect_trait_impls; pub use self::collect_trait_impls::COLLECT_TRAIT_IMPLS; @@ -128,6 +137,7 @@ impl Pass { /// The full list of passes. pub const PASSES: &'static [Pass] = &[ + CHECK_PRIVATE_ITEMS_DOC_TESTS, STRIP_HIDDEN, UNINDENT_COMMENTS, COLLAPSE_DOCS, @@ -141,6 +151,7 @@ pub const PASSES: &'static [Pass] = &[ /// The list of passes run by default. pub const DEFAULT_PASSES: &'static [&'static str] = &[ "collect-trait-impls", + "check-private-items-doc-tests", "strip-hidden", "strip-private", "collect-intra-doc-links", @@ -152,6 +163,7 @@ pub const DEFAULT_PASSES: &'static [&'static str] = &[ /// The list of default passes run with `--document-private-items` is passed to rustdoc. pub const DEFAULT_PRIVATE_PASSES: &'static [&'static str] = &[ "collect-trait-impls", + "check-private-items-doc-tests", "strip-priv-imports", "collect-intra-doc-links", "collapse-docs", @@ -348,3 +360,49 @@ impl fold::DocFolder for ImportStripper { } } } + +pub fn look_for_tests<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx>( + cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>, + dox: &str, + item: &Item, + check_missing_code: bool, +) { + if cx.as_local_node_id(item.def_id).is_none() { + // If non-local, no need to check anything. + return; + } + + struct Tests { + found_tests: usize, + } + + impl ::test::Tester for Tests { + fn add_test(&mut self, _: String, _: LangString, _: usize) { + self.found_tests += 1; + } + } + + let mut tests = Tests { + found_tests: 0, + }; + + if find_testable_code(&dox, &mut tests, ErrorCodes::No).is_ok() { + if check_missing_code == true && tests.found_tests == 0 { + let mut diag = cx.tcx.struct_span_lint_node( + lint::builtin::MISSING_DOC_CODE_EXAMPLES, + NodeId::from_u32(0), + span_of_attrs(&item.attrs), + "Missing code example in this documentation"); + diag.emit(); + } else if check_missing_code == false && + tests.found_tests > 0 && + !cx.renderinfo.borrow().access_levels.is_doc_reachable(item.def_id) { + let mut diag = cx.tcx.struct_span_lint_node( + lint::builtin::PRIVATE_DOC_TESTS, + NodeId::from_u32(0), + span_of_attrs(&item.attrs), + "Documentation test in private item"); + diag.emit(); + } + } +} diff --git a/src/librustdoc/passes/private_items_doc_tests.rs b/src/librustdoc/passes/private_items_doc_tests.rs new file mode 100644 index 00000000000..7c5ce8894b1 --- /dev/null +++ b/src/librustdoc/passes/private_items_doc_tests.rs @@ -0,0 +1,49 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use clean::*; + +use core::DocContext; +use fold::DocFolder; + +use passes::{look_for_tests, Pass}; + +pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = + Pass::early("check-private-items-doc-tests", check_private_items_doc_tests, + "check private items doc tests"); + +struct PrivateItemDocTestLinter<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { + cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>, +} + +impl<'a, 'tcx, 'rcx, 'cstore> PrivateItemDocTestLinter<'a, 'tcx, 'rcx, 'cstore> { + fn new(cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self { + PrivateItemDocTestLinter { + cx, + } + } +} + +pub fn check_private_items_doc_tests(krate: Crate, cx: &DocContext) -> Crate { + let mut coll = PrivateItemDocTestLinter::new(cx); + + coll.fold_crate(krate) +} + +impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for PrivateItemDocTestLinter<'a, 'tcx, 'rcx, 'cstore> { + fn fold_item(&mut self, item: Item) -> Option { + let cx = self.cx; + let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new); + + look_for_tests(&cx, &dox, &item, false); + + self.fold_item_recur(item) + } +} diff --git a/src/test/rustdoc-ui/private-item-doc-test.rs b/src/test/rustdoc-ui/private-item-doc-test.rs new file mode 100644 index 00000000000..5a13fe359f5 --- /dev/null +++ b/src/test/rustdoc-ui/private-item-doc-test.rs @@ -0,0 +1,20 @@ +// Copyright 2018 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. + +#![deny(private_doc_tests)] + +mod foo { + /// private doc test + /// + /// ``` + /// assert!(false); + /// ``` + fn bar() {} +} diff --git a/src/test/rustdoc-ui/private-item-doc-test.stderr b/src/test/rustdoc-ui/private-item-doc-test.stderr new file mode 100644 index 00000000000..b43add7ea50 --- /dev/null +++ b/src/test/rustdoc-ui/private-item-doc-test.stderr @@ -0,0 +1,16 @@ +error: Documentation test in private item + --> $DIR/private-item-doc-test.rs:14:5 + | +LL | / /// private doc test +LL | | /// +LL | | /// ``` +LL | | /// assert!(false); +LL | | /// ``` + | |___________^ + | +note: lint level defined here + --> $DIR/private-item-doc-test.rs:11:9 + | +LL | #![deny(private_doc_tests)] + | ^^^^^^^^^^^^^^^^^ + From 6e099a698699d81eb2d18bf467ca75041a78bf4c Mon Sep 17 00:00:00 2001 From: daniellimws Date: Sat, 17 Nov 2018 00:21:23 +0800 Subject: [PATCH 0038/1984] Add double quotes to resolve error --- src/liballoc/boxed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 8826a836a91..1f1a4f249c7 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -481,7 +481,7 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { /// let slice: &[u8] = &[104, 101, 108, 108, 111]; /// let boxed_slice = Box::from(slice); /// - /// println!({:?}, boxed_slice); + /// println!("{:?}", boxed_slice); /// ``` fn from(slice: &'a [T]) -> Box<[T]> { let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() }; From 4c4aff9b3d1734a1dfb127ce8732728edc5b39ed Mon Sep 17 00:00:00 2001 From: Axary Date: Fri, 16 Nov 2018 18:28:23 +0100 Subject: [PATCH 0039/1984] remove license --- src/test/ui/bare-function-self.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/test/ui/bare-function-self.rs b/src/test/ui/bare-function-self.rs index 01189ae321b..0a430aee973 100644 --- a/src/test/ui/bare-function-self.rs +++ b/src/test/ui/bare-function-self.rs @@ -1,14 +1,3 @@ -// Copyright 2018 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. - - fn a(&self) { } //~^ ERROR unexpected `self` argument in bare function From 646d68f585e6cbabba5b7a67665af9a1f83ea6ea Mon Sep 17 00:00:00 2001 From: Axary Date: Fri, 16 Nov 2018 18:43:06 +0100 Subject: [PATCH 0040/1984] add a note to the error message --- src/libsyntax/parse/parser.rs | 5 ++++- src/test/ui/bare-function-self.rs | 1 + src/test/ui/bare-function-self.stderr | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index dd1864ce124..7ddb4099e0e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5388,7 +5388,10 @@ impl<'a> Parser<'a> { self.expect(&token::OpenDelim(token::Paren))?; if let Ok(Some(_)) = self.parse_self_arg() { - return Err(self.fatal("unexpected `self` argument in bare function")) + let mut err = self.struct_span_err(self.prev_span + , "unexpected `self` argument in bare function"); + err.span_label(self.prev_span, "invalid argument in bare function"); + return Err(err); } let sp = self.span; diff --git a/src/test/ui/bare-function-self.rs b/src/test/ui/bare-function-self.rs index 0a430aee973..f906b176d92 100644 --- a/src/test/ui/bare-function-self.rs +++ b/src/test/ui/bare-function-self.rs @@ -1,4 +1,5 @@ fn a(&self) { } //~^ ERROR unexpected `self` argument in bare function +//~| NOTE invalid argument in bare function fn main() { } diff --git a/src/test/ui/bare-function-self.stderr b/src/test/ui/bare-function-self.stderr index 51db0ddd70d..002d71b1103 100644 --- a/src/test/ui/bare-function-self.stderr +++ b/src/test/ui/bare-function-self.stderr @@ -1,8 +1,8 @@ error: unexpected `self` argument in bare function - --> $DIR/bare-function-self.rs:12:11 + --> $DIR/bare-function-self.rs:1:7 | LL | fn a(&self) { } - | ^ + | ^^^^ invalid argument in bare function error: aborting due to previous error From fe23ffbda01d2033c98ec6cec7f51cb08f625ec9 Mon Sep 17 00:00:00 2001 From: Axary Date: Fri, 16 Nov 2018 19:27:27 +0100 Subject: [PATCH 0041/1984] improve error when self is used as not the first argument --- src/libsyntax/parse/parser.rs | 17 +++++++++-------- src/test/ui/bare-function-self.rs | 5 ----- .../ui/invalid-self-argument/bare-fn-start.rs | 5 +++++ src/test/ui/invalid-self-argument/bare-fn.rs | 5 +++++ src/test/ui/invalid-self-argument/trait-fn.rs | 11 +++++++++++ 5 files changed, 30 insertions(+), 13 deletions(-) delete mode 100644 src/test/ui/bare-function-self.rs create mode 100644 src/test/ui/invalid-self-argument/bare-fn-start.rs create mode 100644 src/test/ui/invalid-self-argument/bare-fn.rs create mode 100644 src/test/ui/invalid-self-argument/trait-fn.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 7ddb4099e0e..a4b01f485d3 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1824,6 +1824,14 @@ impl<'a> Parser<'a> { fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> { maybe_whole!(self, NtArg, |x| x); + if let Ok(Some(_)) = self.parse_self_arg() { + let mut err = self.struct_span_err(self.prev_span, + "unexpected `self` argument in function"); + err.span_label(self.prev_span, + "`self` is only valid as the first argument of a trait function"); + return Err(err); + } + let (pat, ty) = if require_name || self.is_named_argument() { debug!("parse_arg_general parse_pat (require_name:{})", require_name); @@ -5386,14 +5394,7 @@ impl<'a> Parser<'a> { fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool) -> PResult<'a, (Vec , bool)> { self.expect(&token::OpenDelim(token::Paren))?; - - if let Ok(Some(_)) = self.parse_self_arg() { - let mut err = self.struct_span_err(self.prev_span - , "unexpected `self` argument in bare function"); - err.span_label(self.prev_span, "invalid argument in bare function"); - return Err(err); - } - + let sp = self.span; let mut variadic = false; let args: Vec> = diff --git a/src/test/ui/bare-function-self.rs b/src/test/ui/bare-function-self.rs deleted file mode 100644 index f906b176d92..00000000000 --- a/src/test/ui/bare-function-self.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn a(&self) { } -//~^ ERROR unexpected `self` argument in bare function -//~| NOTE invalid argument in bare function - -fn main() { } diff --git a/src/test/ui/invalid-self-argument/bare-fn-start.rs b/src/test/ui/invalid-self-argument/bare-fn-start.rs new file mode 100644 index 00000000000..a84fe55502d --- /dev/null +++ b/src/test/ui/invalid-self-argument/bare-fn-start.rs @@ -0,0 +1,5 @@ +fn a(&self) { } +//~^ ERROR unexpected `self` argument in function +//~| NOTE `self` is only valid as the first argument of a trait function + +fn main() { } diff --git a/src/test/ui/invalid-self-argument/bare-fn.rs b/src/test/ui/invalid-self-argument/bare-fn.rs new file mode 100644 index 00000000000..27e56a53713 --- /dev/null +++ b/src/test/ui/invalid-self-argument/bare-fn.rs @@ -0,0 +1,5 @@ +fn b(foo: u32, &mut self) { } +//~^ ERROR unexpected `self` argument in function +//~| NOTE `self` is only valid as the first argument of a trait function + +fn main() { } diff --git a/src/test/ui/invalid-self-argument/trait-fn.rs b/src/test/ui/invalid-self-argument/trait-fn.rs new file mode 100644 index 00000000000..e2107e4d867 --- /dev/null +++ b/src/test/ui/invalid-self-argument/trait-fn.rs @@ -0,0 +1,11 @@ +struct Foo {} + +impl Foo { + fn c(foo: u32, self) {} + //~^ ERROR unexpected `self` argument in function + //~| NOTE `self` is only valid as the first argument of a trait function + + fn good(&mut self, foo: u32) {} +} + +fn main() { } From 2be930bd03d3c9b9230ae3b9cc8fc30b83378900 Mon Sep 17 00:00:00 2001 From: Axary Date: Fri, 16 Nov 2018 19:35:13 +0100 Subject: [PATCH 0042/1984] fix tidy (remove whitespace) --- src/libsyntax/parse/parser.rs | 2 +- src/test/ui/invalid-self-argument/bare-fn-start.stderr | 8 ++++++++ src/test/ui/invalid-self-argument/bare-fn.stderr | 8 ++++++++ src/test/ui/invalid-self-argument/trait-fn.stderr | 8 ++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/invalid-self-argument/bare-fn-start.stderr create mode 100644 src/test/ui/invalid-self-argument/bare-fn.stderr create mode 100644 src/test/ui/invalid-self-argument/trait-fn.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a4b01f485d3..18929af4718 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5394,7 +5394,7 @@ impl<'a> Parser<'a> { fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool) -> PResult<'a, (Vec , bool)> { self.expect(&token::OpenDelim(token::Paren))?; - + let sp = self.span; let mut variadic = false; let args: Vec> = diff --git a/src/test/ui/invalid-self-argument/bare-fn-start.stderr b/src/test/ui/invalid-self-argument/bare-fn-start.stderr new file mode 100644 index 00000000000..d0eca1a9e5c --- /dev/null +++ b/src/test/ui/invalid-self-argument/bare-fn-start.stderr @@ -0,0 +1,8 @@ +error: unexpected `self` argument in function + --> $DIR/bare-fn-start.rs:1:7 + | +LL | fn a(&self) { } + | ^^^^ `self` is only valid as the first argument of a trait function + +error: aborting due to previous error + diff --git a/src/test/ui/invalid-self-argument/bare-fn.stderr b/src/test/ui/invalid-self-argument/bare-fn.stderr new file mode 100644 index 00000000000..bd6c598c88a --- /dev/null +++ b/src/test/ui/invalid-self-argument/bare-fn.stderr @@ -0,0 +1,8 @@ +error: unexpected `self` argument in function + --> $DIR/bare-fn.rs:1:21 + | +LL | fn b(foo: u32, &mut self) { } + | ^^^^ `self` is only valid as the first argument of a trait function + +error: aborting due to previous error + diff --git a/src/test/ui/invalid-self-argument/trait-fn.stderr b/src/test/ui/invalid-self-argument/trait-fn.stderr new file mode 100644 index 00000000000..d056e53b95c --- /dev/null +++ b/src/test/ui/invalid-self-argument/trait-fn.stderr @@ -0,0 +1,8 @@ +error: unexpected `self` argument in function + --> $DIR/trait-fn.rs:4:20 + | +LL | fn c(foo: u32, self) {} + | ^^^^ `self` is only valid as the first argument of a trait function + +error: aborting due to previous error + From 5bfdcc1ab1c94baa4865093b6c36fb15416e6a4d Mon Sep 17 00:00:00 2001 From: Axary Date: Sat, 17 Nov 2018 09:36:56 +0100 Subject: [PATCH 0043/1984] remove stray file with UI testing output --- src/test/ui/bare-function-self.stderr | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 src/test/ui/bare-function-self.stderr diff --git a/src/test/ui/bare-function-self.stderr b/src/test/ui/bare-function-self.stderr deleted file mode 100644 index 002d71b1103..00000000000 --- a/src/test/ui/bare-function-self.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: unexpected `self` argument in bare function - --> $DIR/bare-function-self.rs:1:7 - | -LL | fn a(&self) { } - | ^^^^ invalid argument in bare function - -error: aborting due to previous error - From d93e5b04f4817718480d17eafa0ee5e7bbe1f019 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 17 Nov 2018 17:57:17 +0800 Subject: [PATCH 0044/1984] reserve whitespaces between prefix and pipe --- src/librustc/traits/error_reporting.rs | 2 +- src/test/ui/mismatched_types/closure-arg-count.rs | 2 +- src/test/ui/mismatched_types/closure-arg-count.stderr | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index d08a4b47b31..48b2b25d6ad 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1097,7 +1097,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // // move |_| { ... } // ^^^^^-- prefix - let prefix_span = self.tcx.sess.source_map().span_until_char(found_span, '|'); + let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span); // move |_| { ... } // ^^^-- pipe_span let pipe_span = if let Some(span) = found_span.trim_start(prefix_span) { diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs index ed9162d2348..2dcc7a25c84 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.rs +++ b/src/test/ui/mismatched_types/closure-arg-count.rs @@ -22,7 +22,7 @@ fn main() { //~^ ERROR closure is expected to take f(|| panic!()); //~^ ERROR closure is expected to take - f(move || panic!()); + f( move || panic!()); //~^ ERROR closure is expected to take let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i); diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 89977aadf88..eeadf07262c 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -63,8 +63,8 @@ LL | f(|_| panic!()); error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments --> $DIR/closure-arg-count.rs:25:5 | -LL | f(move || panic!()); - | ^ ------- takes 0 arguments +LL | f( move || panic!()); + | ^ ---------- takes 0 arguments | | | expected closure that takes 1 argument | @@ -75,8 +75,8 @@ LL | fn f>(_: F) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the closure to take and ignore the expected argument | -LL | f(move|_| panic!()); - | ^^^ +LL | f( move |_| panic!()); + | ^^^ error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments --> $DIR/closure-arg-count.rs:28:53 From 1d808d106bc88be89eba1354e5dd724bb5816726 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Nov 2018 13:50:04 +0100 Subject: [PATCH 0045/1984] When popping in CTFE, perform validation before jumping to next statement to have a better span for the error --- src/librustc_mir/interpret/eval_context.rs | 33 +++++++++++----------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index e6267012dc2..f9c28753c2d 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -492,23 +492,6 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc let frame = self.stack.pop().expect( "tried to pop a stack frame, but there were none", ); - match frame.return_to_block { - StackPopCleanup::Goto(block) => { - self.goto_block(block)?; - } - StackPopCleanup::None { cleanup } => { - if !cleanup { - // Leak the locals. Also skip validation, this is only used by - // static/const computation which does its own (stronger) final - // validation. - return Ok(()); - } - } - } - // Deallocate all locals that are backed by an allocation. - for local in frame.locals { - self.deallocate_local(local)?; - } // Validate the return value. if let Some(return_place) = frame.return_place { if M::enforce_validity(self) { @@ -530,6 +513,22 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc // Uh, that shouldn't happen... the function did not intend to return return err!(Unreachable); } + // Jump to new block -- *after* validation so that the spans make more sense. + match frame.return_to_block { + StackPopCleanup::Goto(block) => { + self.goto_block(block)?; + } + StackPopCleanup::None { cleanup } => { + if !cleanup { + // Leak the locals. + return Ok(()); + } + } + } + // Deallocate all locals that are backed by an allocation. + for local in frame.locals { + self.deallocate_local(local)?; + } if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... debug!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance); From 3d33d05c81f949f743b3441cc1e960f2dc2bd5ac Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 17 Nov 2018 13:55:35 +0100 Subject: [PATCH 0046/1984] We're looking at the miri memory for constants instead of their initializers' MIR --- src/librustc_mir/monomorphize/collector.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 8e27635dee8..92318755ff5 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -178,10 +178,6 @@ //! Some things are not yet fully implemented in the current version of this //! module. //! -//! ### Initializers of Constants and Statics -//! Since no MIR is constructed yet for initializer expressions of constants and -//! statics we cannot inspect these properly. -//! //! ### Const Fns //! Ideally, no mono item should be generated for const fns unless there //! is a call to them that cannot be evaluated at compile time. At the moment From bcf82efe081dd12e4b6708241f5a1d165d103cae Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Nov 2018 14:51:45 +0100 Subject: [PATCH 0047/1984] deallocate locals before validation, to catch dangling references --- src/librustc_mir/interpret/eval_context.rs | 30 ++++++++++++++-------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index f9c28753c2d..148442deaad 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -492,7 +492,24 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc let frame = self.stack.pop().expect( "tried to pop a stack frame, but there were none", ); - // Validate the return value. + // Abort early if we do not want to clean up: We also avoid validation in that case, + // because this is CTFE and the final value will be thoroughly validated anyway. + match frame.return_to_block { + StackPopCleanup::Goto(_) => {}, + StackPopCleanup::None { cleanup } => { + if !cleanup { + assert!(self.stack.is_empty(), "only the topmost frame should ever be leaked"); + // Leak the locals, skip validation. + return Ok(()); + } + } + } + // Deallocate all locals that are backed by an allocation. + for local in frame.locals { + self.deallocate_local(local)?; + } + // Validate the return value. Do this after deallocating so that we catch dangling + // references. if let Some(return_place) = frame.return_place { if M::enforce_validity(self) { // Data got changed, better make sure it matches the type! @@ -518,16 +535,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc StackPopCleanup::Goto(block) => { self.goto_block(block)?; } - StackPopCleanup::None { cleanup } => { - if !cleanup { - // Leak the locals. - return Ok(()); - } - } - } - // Deallocate all locals that are backed by an allocation. - for local in frame.locals { - self.deallocate_local(local)?; + StackPopCleanup::None { .. } => {} } if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... From ef99b57b13f9ab04f44dd9c5c325be8f0b6b9dc1 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 17 Nov 2018 15:05:12 +0100 Subject: [PATCH 0048/1984] Refactor local monomorphization logic to be easier to comprehend --- src/librustc_mir/monomorphize/collector.rs | 43 +++++++++++----------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 92318755ff5..977285b27be 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -187,7 +187,6 @@ use rustc::hir::{self, CodegenFnAttrFlags}; use rustc::hir::itemlikevisit::ItemLikeVisitor; -use rustc::hir::Node; use rustc::hir::def_id::DefId; use rustc::mir::interpret::{AllocId, ConstValue}; use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem}; @@ -737,27 +736,27 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: ty::InstanceDef::CloneShim(..) => return true }; - return match tcx.hir.get_if_local(def_id) { - Some(Node::ForeignItem(..)) => { - false // foreign items are linked against, not codegened. - } - Some(_) => true, - None => { - if tcx.is_reachable_non_generic(def_id) || - tcx.is_foreign_item(def_id) || - is_available_upstream_generic(tcx, def_id, instance.substs) - { - // We can link to the item in question, no instance needed - // in this crate - false - } else { - if !tcx.is_mir_available(def_id) { - bug!("Cannot create local mono-item for {:?}", def_id) - } - true - } - } - }; + if tcx.is_foreign_item(def_id) { + // We can always link to foreign items + return false; + } + + if def_id.is_local() { + // local items cannot be referred to locally without monomorphizing them locally + return true; + } + + if tcx.is_reachable_non_generic(def_id) || + is_available_upstream_generic(tcx, def_id, instance.substs) { + // We can link to the item in question, no instance needed + // in this crate + return false; + } + + if !tcx.is_mir_available(def_id) { + bug!("Cannot create local mono-item for {:?}", def_id) + } + return true; fn is_available_upstream_generic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, From eb18ddd8f4fede5e12a97f724014a8406dd75881 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 17 Nov 2018 15:36:06 +0100 Subject: [PATCH 0049/1984] Don't auto-inline `const fn` --- src/librustc/ty/instance.rs | 5 +---- .../item-collection/unreferenced-const-fn.rs | 3 +-- src/test/ui/consts/auxiliary/const_fn_lib.rs | 20 ++++++++++++++++++- .../consts/const_fn_return_nested_fn_ptr.rs | 10 ++++++++++ 4 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/consts/const_fn_return_nested_fn_ptr.rs diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index b6691df39c1..411a6e7e623 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -173,10 +173,7 @@ impl<'tcx> InstanceDef<'tcx> { // available to normal end-users. return true } - let codegen_fn_attrs = tcx.codegen_fn_attrs(self.def_id()); - // need to use `is_const_fn_raw` since we don't really care if the user can use it as a - // const fn, just whether the function should be inlined - codegen_fn_attrs.requests_inline() || tcx.is_const_fn_raw(self.def_id()) + tcx.codegen_fn_attrs(self.def_id()).requests_inline() } } diff --git a/src/test/codegen-units/item-collection/unreferenced-const-fn.rs b/src/test/codegen-units/item-collection/unreferenced-const-fn.rs index c4a49fd4ec4..5e181870fed 100644 --- a/src/test/codegen-units/item-collection/unreferenced-const-fn.rs +++ b/src/test/codegen-units/item-collection/unreferenced-const-fn.rs @@ -11,11 +11,10 @@ // ignore-tidy-linelength // compile-flags:-Zprint-mono-items=lazy -// NB: We do not expect *any* monomorphization to be generated here. - #![deny(dead_code)] #![crate_type = "rlib"] +//~ MONO_ITEM fn unreferenced_const_fn::foo[0] @@ unreferenced_const_fn-cgu.0[External] pub const fn foo(x: u32) -> u32 { x + 0xf00 } diff --git a/src/test/ui/consts/auxiliary/const_fn_lib.rs b/src/test/ui/consts/auxiliary/const_fn_lib.rs index 5063c8d1d1f..72369aae97c 100644 --- a/src/test/ui/consts/auxiliary/const_fn_lib.rs +++ b/src/test/ui/consts/auxiliary/const_fn_lib.rs @@ -10,6 +10,24 @@ // Crate that exports a const fn. Used for testing cross-crate. +#![feature(const_fn)] #![crate_type="rlib"] -pub const fn foo() -> usize { 22 } //~ ERROR const fn is unstable +pub const fn foo() -> usize { 22 } + +pub const fn bar() -> fn() { + fn x() {} + x +} + +#[inline] +pub const fn bar_inlined() -> fn() { + fn x() {} + x +} + +#[inline(always)] +pub const fn bar_inlined_always() -> fn() { + fn x() {} + x +} diff --git a/src/test/ui/consts/const_fn_return_nested_fn_ptr.rs b/src/test/ui/consts/const_fn_return_nested_fn_ptr.rs new file mode 100644 index 00000000000..c7617c9c7ad --- /dev/null +++ b/src/test/ui/consts/const_fn_return_nested_fn_ptr.rs @@ -0,0 +1,10 @@ +// compile-pass +// aux-build:const_fn_lib.rs + +extern crate const_fn_lib; + +fn main() { + const_fn_lib::bar()(); + const_fn_lib::bar_inlined()(); + const_fn_lib::bar_inlined_always()(); +} From cc63bd47efe4387982b399e2397adab6ac4030ef Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Sat, 17 Nov 2018 14:48:18 +0100 Subject: [PATCH 0050/1984] atomic::Ordering: Get rid of misleading parts of intro Remove the parts of atomic::Ordering's intro that wrongly claimed that SeqCst prevents all reorderings around it. Closes #55196 --- src/libcore/sync/atomic.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 56d3b429fdb..27eeb045bb1 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -173,11 +173,11 @@ unsafe impl Sync for AtomicPtr {} /// Atomic memory orderings /// -/// Memory orderings limit the ways that both the compiler and CPU may reorder -/// instructions around atomic operations. At its most restrictive, -/// "sequentially consistent" atomics allow neither reads nor writes -/// to be moved either before or after the atomic operation; on the other end -/// "relaxed" atomics allow all reorderings. +/// Memory orderings specify the way atomic operations synchronize memory. +/// In its weakest [`Relaxed`][Ordering::Relaxed], only the memory directly touched by the +/// operation is synchronized. On the other hand, a store-load pair of [`SeqCst`][Ordering::SeqCst] +/// operations synchronize other memory while additionally preserving a total order of such +/// operations across all threads. /// /// Rust's memory orderings are [the same as /// LLVM's](https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations). @@ -185,6 +185,8 @@ unsafe impl Sync for AtomicPtr {} /// For more information see the [nomicon]. /// /// [nomicon]: ../../../nomicon/atomics.html +/// [Ordering::Relaxed]: #variant.Relaxed +/// [Ordering::SeqCst]: #variant.SeqCst #[stable(feature = "rust1", since = "1.0.0")] #[derive(Copy, Clone, Debug)] #[non_exhaustive] @@ -234,8 +236,8 @@ pub enum Ordering { /// For loads it uses [`Acquire`] ordering. For stores it uses the [`Release`] ordering. /// /// Notice that in the case of `compare_and_swap`, it is possible that the operation ends up - /// not performing any store and hence it has just `Acquire` ordering. However, - /// `AcqRel` will never perform [`Relaxed`] accesses. + /// not performing any store and hence it has just [`Acquire`] ordering. However, + /// [`AcqRel`][`AcquireRelease`] will never perform [`Relaxed`] accesses. /// /// This ordering is only applicable for operations that combine both loads and stores. /// From b16985a3546844e14842b9c15ddc50aff9f1adda Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 10 Nov 2018 23:02:13 +0000 Subject: [PATCH 0051/1984] Remove mir::StatementKind::EndRegion Since lexical MIR borrow check is gone, and validation no longer uses these, they can be removed. --- src/librustc/ich/impls_mir.rs | 3 - src/librustc/mir/mod.rs | 8 - src/librustc/mir/visit.rs | 1 - src/librustc/session/config.rs | 2 - src/librustc/ty/context.rs | 7 - src/librustc_codegen_ssa/mir/statement.rs | 1 - src/librustc_mir/borrow_check/mod.rs | 4 - .../borrow_check/nll/invalidation.rs | 2 - src/librustc_mir/borrow_check/nll/renumber.rs | 14 +- .../borrow_check/nll/type_check/mod.rs | 1 - src/librustc_mir/build/cfg.rs | 26 --- src/librustc_mir/build/scope.rs | 15 +- src/librustc_mir/dataflow/impls/borrows.rs | 6 +- .../dataflow/move_paths/builder.rs | 1 - src/librustc_mir/interpret/step.rs | 1 - src/librustc_mir/transform/check_unsafety.rs | 1 - .../transform/cleanup_post_borrowck.rs | 109 ++----------- src/librustc_mir/transform/erase_regions.rs | 6 +- src/librustc_mir/transform/mod.rs | 3 - src/librustc_mir/transform/qualify_consts.rs | 1 - .../transform/qualify_min_const_fn.rs | 1 - .../transform/remove_noop_landing_pads.rs | 5 +- src/librustc_mir/transform/rustc_peek.rs | 1 - src/librustc_passes/mir_stats.rs | 1 - src/test/mir-opt/end_region_1.rs | 42 ----- src/test/mir-opt/end_region_2.rs | 81 --------- src/test/mir-opt/end_region_3.rs | 81 --------- src/test/mir-opt/end_region_4.rs | 83 ---------- src/test/mir-opt/end_region_5.rs | 77 --------- src/test/mir-opt/end_region_6.rs | 83 ---------- src/test/mir-opt/end_region_7.rs | 91 ----------- src/test/mir-opt/end_region_8.rs | 83 ---------- src/test/mir-opt/end_region_9.rs | 97 ----------- src/test/mir-opt/end_region_cyclic.rs | 141 ---------------- .../end_region_destruction_extents_1.rs | 154 ------------------ src/test/mir-opt/issue-43457.rs | 55 ------- src/test/mir-opt/loop_test.rs | 2 +- src/test/run-pass/issues/issue-16671.rs | 2 +- src/test/ui/borrowck/immutable-arg.rs | 2 +- src/test/ui/issues/issue-45697-1.rs | 2 +- src/test/ui/issues/issue-45697.rs | 2 +- src/test/ui/issues/issue-46023.rs | 2 +- src/test/ui/issues/issue-46471-1.rs | 2 +- src/test/ui/issues/issue-46471.rs | 2 +- src/test/ui/issues/issue-46472.rs | 2 +- .../ui/moves/moves-based-on-type-tuple.rs | 2 +- .../maybe-initialized-drop-uninitialized.rs | 2 +- .../maybe-initialized-drop-with-fragment.rs | 2 +- ...lized-drop-with-uninitialized-fragments.rs | 2 +- src/test/ui/nll/maybe-initialized-drop.rs | 2 +- 50 files changed, 33 insertions(+), 1283 deletions(-) delete mode 100644 src/test/mir-opt/end_region_1.rs delete mode 100644 src/test/mir-opt/end_region_2.rs delete mode 100644 src/test/mir-opt/end_region_3.rs delete mode 100644 src/test/mir-opt/end_region_4.rs delete mode 100644 src/test/mir-opt/end_region_5.rs delete mode 100644 src/test/mir-opt/end_region_6.rs delete mode 100644 src/test/mir-opt/end_region_7.rs delete mode 100644 src/test/mir-opt/end_region_8.rs delete mode 100644 src/test/mir-opt/end_region_9.rs delete mode 100644 src/test/mir-opt/end_region_cyclic.rs delete mode 100644 src/test/mir-opt/end_region_destruction_extents_1.rs delete mode 100644 src/test/mir-opt/issue-43457.rs diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index d6ad74f16a9..d98bb82aaba 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -217,9 +217,6 @@ for mir::StatementKind<'gcx> { mir::StatementKind::StorageDead(ref place) => { place.hash_stable(hcx, hasher); } - mir::StatementKind::EndRegion(ref region_scope) => { - region_scope.hash_stable(hcx, hasher); - } mir::StatementKind::EscapeToRaw(ref place) => { place.hash_stable(hcx, hasher); } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index d8e45c881f5..a9ea1c9a109 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -15,7 +15,6 @@ use hir::def::CtorKind; use hir::def_id::DefId; use hir::{self, HirId, InlineAsm}; -use middle::region; use mir::interpret::{ConstValue, EvalErrorKind, Scalar}; use mir::visit::MirVisitable; use rustc_apfloat::ieee::{Double, Single}; @@ -1789,10 +1788,6 @@ pub enum StatementKind<'tcx> { /// for more details. EscapeToRaw(Operand<'tcx>), - /// Mark one terminating point of a region scope (i.e. static region). - /// (The starting point(s) arise implicitly from borrows.) - EndRegion(region::Scope), - /// Encodes a user's type ascription. These need to be preserved /// intact so that NLL can respect them. For example: /// @@ -1846,8 +1841,6 @@ impl<'tcx> Debug for Statement<'tcx> { match self.kind { Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv), FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place), - // (reuse lifetime rendering policy from ppaux.) - EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)), Retag { fn_entry, ref place } => write!(fmt, "Retag({}{:?})", if fn_entry { "[fn entry] " } else { "" }, place), EscapeToRaw(ref place) => write!(fmt, "EscapeToRaw({:?})", place), @@ -3028,7 +3021,6 @@ EnumTypeFoldableImpl! { (StatementKind::InlineAsm) { asm, outputs, inputs }, (StatementKind::Retag) { fn_entry, place }, (StatementKind::EscapeToRaw)(place), - (StatementKind::EndRegion)(a), (StatementKind::AscribeUserType)(a, v, b), (StatementKind::Nop), } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 2a994ee0509..0c9b06a8d8c 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -377,7 +377,6 @@ macro_rules! make_mir_visitor { location ); } - StatementKind::EndRegion(_) => {} StatementKind::SetDiscriminant{ ref $($mutability)* place, .. } => { self.visit_place( place, diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index ee6d970750a..92a808bbda2 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1149,8 +1149,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "when debug-printing compiler state, do not include spans"), // o/w tests have closure@path identify_regions: bool = (false, parse_bool, [UNTRACKED], "make unnamed regions display as '# (where # is some non-ident unique id)"), - emit_end_regions: bool = (false, parse_bool, [UNTRACKED], - "emit EndRegion as part of MIR; enable transforms that solely process EndRegion"), borrowck: Option = (None, parse_opt_string, [UNTRACKED], "select which borrowck is used (`ast`, `mir`, `migrate`, or `compare`)"), two_phase_borrows: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index cdfe8f53b85..1d81ab19961 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1540,13 +1540,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - /// Should we emit EndRegion MIR statements? These are consumed by - /// MIR borrowck, but not when NLL is used. - pub fn emit_end_regions(self) -> bool { - self.sess.opts.debugging_opts.emit_end_regions || - self.use_mir_borrowck() - } - #[inline] pub fn local_crate_exports_generics(self) -> bool { debug_assert!(self.sess.opts.share_generics()); diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs index a69474142ab..0d058c85f33 100644 --- a/src/librustc_codegen_ssa/mir/statement.rs +++ b/src/librustc_codegen_ssa/mir/statement.rs @@ -105,7 +105,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx } mir::StatementKind::FakeRead(..) | - mir::StatementKind::EndRegion(..) | mir::StatementKind::Retag { .. } | mir::StatementKind::EscapeToRaw { .. } | mir::StatementKind::AscribeUserType(..) | diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index f0d3b863f78..8819908de6a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -592,10 +592,6 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx self.consume_operand(context, (input, span), flow_state); } } - StatementKind::EndRegion(ref _rgn) => { - // ignored when consuming results (update to - // flow_state already handled). - } StatementKind::Nop | StatementKind::AscribeUserType(..) | StatementKind::Retag { .. } diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 576509c0fdd..8af23a8813a 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -132,8 +132,6 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> { self.consume_operand(context, input); } } - // EndRegion matters to older NLL/MIR AST borrowck, not to alias NLL - StatementKind::EndRegion(..) | StatementKind::Nop | StatementKind::AscribeUserType(..) | StatementKind::Retag { .. } | diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 363afb87ed9..e9f749ac092 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -10,7 +10,7 @@ use rustc::ty::subst::Substs; use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable}; -use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind, UserTypeAnnotation}; +use rustc::mir::{Location, Mir, UserTypeAnnotation}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; @@ -119,16 +119,4 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> { debug!("visit_closure_substs: substs={:?}", substs); } - - fn visit_statement( - &mut self, - block: BasicBlock, - statement: &mut Statement<'tcx>, - location: Location, - ) { - if let StatementKind::EndRegion(_) = statement.kind { - statement.kind = StatementKind::Nop; - } - self.super_statement(block, statement, location); - } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 06dfd4bc2cc..b978d8c9d0a 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1314,7 +1314,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { | StatementKind::StorageLive(..) | StatementKind::StorageDead(..) | StatementKind::InlineAsm { .. } - | StatementKind::EndRegion(_) | StatementKind::Retag { .. } | StatementKind::EscapeToRaw { .. } | StatementKind::Nop => {} diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 619ebb1675c..2efb75c232d 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -14,9 +14,7 @@ //! Routines for manipulating the control-flow graph. use build::CFG; -use rustc::middle::region; use rustc::mir::*; -use rustc::ty::TyCtxt; impl<'tcx> CFG<'tcx> { pub fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> { @@ -45,30 +43,6 @@ impl<'tcx> CFG<'tcx> { self.block_data_mut(block).statements.push(statement); } - pub fn push_end_region<'a, 'gcx:'a+'tcx>(&mut self, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - block: BasicBlock, - source_info: SourceInfo, - region_scope: region::Scope) { - if tcx.emit_end_regions() { - if let region::ScopeData::CallSite = region_scope.data { - // The CallSite scope (aka the root scope) is sort of weird, in that it is - // supposed to "separate" the "interior" and "exterior" of a closure. Being - // that, it is not really a part of the region hierarchy, but for some - // reason it *is* considered a part of it. - // - // It should die a hopefully painful death with NLL, so let's leave this hack - // for now so that nobody can complain about soundness. - return - } - - self.push(block, Statement { - source_info, - kind: StatementKind::EndRegion(region_scope), - }); - } - } - pub fn push_assign(&mut self, block: BasicBlock, source_info: SourceInfo, diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 99badd5a03f..1a8f8fbbb68 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -90,7 +90,7 @@ should go to. use build::{BlockAnd, BlockAndExtension, Builder, CFG}; use hair::LintLevel; use rustc::middle::region; -use rustc::ty::{Ty, TyCtxt}; +use rustc::ty::Ty; use rustc::hir; use rustc::hir::def_id::LOCAL_CRATE; use rustc::mir::*; @@ -381,7 +381,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let scope = self.scopes.pop().unwrap(); assert_eq!(scope.region_scope, region_scope.0); - self.cfg.push_end_region(self.hir.tcx(), block, region_scope.1, scope.region_scope); let resume_block = self.resume_block(); unpack!(block = build_scope_drops(&mut self.cfg, resume_block, @@ -439,9 +438,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { b }; - // End all regions for scopes out of which we are breaking. - self.cfg.push_end_region(self.hir.tcx(), block, region_scope.1, scope.region_scope); - unpack!(block = build_scope_drops(&mut self.cfg, resume_block, scope, @@ -491,9 +487,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { b }; - // End all regions for scopes out of which we are breaking. - self.cfg.push_end_region(self.hir.tcx(), block, src_info, scope.region_scope); - unpack!(block = build_scope_drops(&mut self.cfg, resume_block, scope, @@ -790,7 +783,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if scopes.iter().any(|scope| scope.needs_cleanup) { for scope in scopes.iter_mut() { - target = build_diverge_scope(self.hir.tcx(), cfg, scope.region_scope_span, + target = build_diverge_scope(cfg, scope.region_scope_span, scope, target, generator_drop); } } @@ -950,8 +943,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>, block.unit() } -fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - cfg: &mut CFG<'tcx>, +fn build_diverge_scope<'a, 'gcx, 'tcx>(cfg: &mut CFG<'tcx>, span: Span, scope: &mut Scope<'tcx>, mut target: BasicBlock, @@ -1018,7 +1010,6 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, cached_block } else { let block = cfg.start_new_cleanup_block(); - cfg.push_end_region(tcx, block, source_info(span), scope.region_scope); cfg.terminate(block, source_info(span), TerminatorKind::Goto { target }); *cached_block = Some(block); block diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 811da9e1acc..5e84aa05d38 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -190,8 +190,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { } /// Add all borrows to the kill set, if those borrows are out of scope at `location`. - /// That means either they went out of either a nonlexical scope, if we care about those - /// at the moment, or the location represents a lexical EndRegion + /// That means they went out of a nonlexical scope fn kill_loans_out_of_scope_at_location(&self, sets: &mut BlockSets, location: Location) { @@ -252,9 +251,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { }); match stmt.kind { - mir::StatementKind::EndRegion(_) => { - } - mir::StatementKind::Assign(ref lhs, ref rhs) => { // Make sure there are no remaining borrows for variables // that are assigned over. diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 0e2376d201f..3796b1cc4b0 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -301,7 +301,6 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { span_bug!(stmt.source_info.span, "SetDiscriminant should not exist during borrowck"); } - StatementKind::EndRegion(..) | StatementKind::Retag { .. } | StatementKind::EscapeToRaw { .. } | StatementKind::AscribeUserType(..) | diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index ac13e5982da..8814118f65b 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -129,7 +129,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } // Statements we do not track. - EndRegion(..) => {} AscribeUserType(..) => {} // Defined to do nothing. These are added by optimization passes, to avoid changing the diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 4ebeebca227..3404772f825 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -112,7 +112,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { StatementKind::SetDiscriminant { .. } | StatementKind::StorageLive(..) | StatementKind::StorageDead(..) | - StatementKind::EndRegion(..) | StatementKind::Retag { .. } | StatementKind::EscapeToRaw { .. } | StatementKind::AscribeUserType(..) | diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs index 98311444e28..c0edd3926d3 100644 --- a/src/librustc_mir/transform/cleanup_post_borrowck.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -10,111 +10,26 @@ //! This module provides two passes: //! -//! - `CleanEndRegions`, that reduces the set of `EndRegion` statements -//! in the MIR. -//! - `CleanAscribeUserType`, that replaces all `AscribeUserType` statements -//! with `Nop`. +//! - [CleanAscribeUserType], that replaces all +//! [StatementKind::AscribeUserType] statements with [StatementKind::Nop]. +//! - [CleanFakeReadsAndBorrows], that replaces all [FakeRead] statements and +//! borrows that are read by [FakeReadCause::ForMatchGuard] fake reads with +//! [StatementKind::Nop]. //! -//! The `CleanEndRegions` "pass" is actually implemented as two +//! The [CleanFakeReadsAndBorrows] "pass" is actually implemented as two //! traversals (aka visits) of the input MIR. The first traversal, -//! `GatherBorrowedRegions`, finds all of the regions in the MIR -//! that are involved in a borrow. -//! -//! The second traversal, `DeleteTrivialEndRegions`, walks over the -//! MIR and removes any `EndRegion` that is applied to a region that -//! was not seen in the previous pass. -//! -//! The `CleanAscribeUserType` pass runs at a distinct time from the -//! `CleanEndRegions` pass. It is important that the `CleanAscribeUserType` -//! pass runs after the MIR borrowck so that the NLL type checker can -//! perform the type assertion when it encounters the `AscribeUserType` -//! statements. +//! [DeleteAndRecordFakeReads], deletes the fake reads and finds the temporaries +//! read by [ForMatchGuard] reads, and [DeleteFakeBorrows] deletes the +//! initialization of those temporaries. use rustc_data_structures::fx::FxHashSet; -use rustc::middle::region; use rustc::mir::{BasicBlock, FakeReadCause, Local, Location, Mir, Place}; -use rustc::mir::{Rvalue, Statement, StatementKind}; -use rustc::mir::visit::{MutVisitor, Visitor, TyContext}; -use rustc::ty::{Ty, RegionKind, TyCtxt}; -use smallvec::smallvec; +use rustc::mir::{Statement, StatementKind}; +use rustc::mir::visit::MutVisitor; +use rustc::ty::TyCtxt; use transform::{MirPass, MirSource}; -pub struct CleanEndRegions; - -#[derive(Default)] -struct GatherBorrowedRegions { - seen_regions: FxHashSet, -} - -struct DeleteTrivialEndRegions<'a> { - seen_regions: &'a FxHashSet, -} - -impl MirPass for CleanEndRegions { - fn run_pass<'a, 'tcx>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - _source: MirSource, - mir: &mut Mir<'tcx>) { - if !tcx.emit_end_regions() { return; } - - let mut gather = GatherBorrowedRegions::default(); - gather.visit_mir(mir); - - let mut delete = DeleteTrivialEndRegions { seen_regions: &mut gather.seen_regions }; - delete.visit_mir(mir); - } -} - -impl<'tcx> Visitor<'tcx> for GatherBorrowedRegions { - fn visit_rvalue(&mut self, - rvalue: &Rvalue<'tcx>, - location: Location) { - // Gather regions that are used for borrows - if let Rvalue::Ref(r, _, _) = *rvalue { - if let RegionKind::ReScope(ce) = *r { - self.seen_regions.insert(ce); - } - } - self.super_rvalue(rvalue, location); - } - - fn visit_ty(&mut self, ty: &Ty<'tcx>, _: TyContext) { - // Gather regions that occur in types - let mut regions = smallvec![]; - for t in ty.walk() { - t.push_regions(&mut regions); - } - for re in regions { - match *re { - RegionKind::ReScope(ce) => { self.seen_regions.insert(ce); } - _ => {}, - } - } - self.super_ty(ty); - } -} - -impl<'a, 'tcx> MutVisitor<'tcx> for DeleteTrivialEndRegions<'a> { - fn visit_statement(&mut self, - block: BasicBlock, - statement: &mut Statement<'tcx>, - location: Location) { - let mut delete_it = false; - - if let StatementKind::EndRegion(ref region_scope) = statement.kind { - if !self.seen_regions.contains(region_scope) { - delete_it = true; - } - } - - if delete_it { - statement.make_nop(); - } - self.super_statement(block, statement, location); - } -} - pub struct CleanAscribeUserType; pub struct DeleteAscribeUserType; diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 6351a6b40cb..a5b5a7e86d2 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -12,7 +12,7 @@ //! We want to do this once just before codegen, so codegen does not have to take //! care erasing regions all over the place. //! NOTE: We do NOT erase regions of statements that are relevant for -//! "types-as-contracts"-validation, namely, AcquireValid, ReleaseValid, and EndRegion. +//! "types-as-contracts"-validation, namely, AcquireValid, ReleaseValid use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; @@ -54,10 +54,6 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> { block: BasicBlock, statement: &mut Statement<'tcx>, location: Location) { - if let StatementKind::EndRegion(_) = statement.kind { - statement.kind = StatementKind::Nop; - } - self.super_statement(block, statement, location); } } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 92cfcb3fd56..0a83026fb00 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -209,9 +209,6 @@ fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea let mut mir = tcx.mir_built(def_id).steal(); run_passes(tcx, &mut mir, def_id, MirPhase::Const, &[ - // Remove all `EndRegion` statements that are not involved in borrows. - &cleanup_post_borrowck::CleanEndRegions, - // What we need to do constant evaluation. &simplify::SimplifyCfg::new("initial"), &type_check::TypeckMir, diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 00309b0a3e9..816e8594885 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1168,7 +1168,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::InlineAsm {..} | - StatementKind::EndRegion(_) | StatementKind::Retag { .. } | StatementKind::EscapeToRaw { .. } | StatementKind::AscribeUserType(..) | diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index ed13063cfdf..e567a79d7f2 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -243,7 +243,6 @@ fn check_statement( | StatementKind::StorageDead(_) | StatementKind::Retag { .. } | StatementKind::EscapeToRaw { .. } - | StatementKind::EndRegion(_) | StatementKind::AscribeUserType(..) | StatementKind::Nop => Ok(()), } diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index 445ffbbcf34..a31d12baed2 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -52,12 +52,9 @@ impl RemoveNoopLandingPads { StatementKind::FakeRead(..) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | - StatementKind::EndRegion(_) | StatementKind::AscribeUserType(..) | StatementKind::Nop => { - // These are all nops in a landing pad (there's some - // borrowck interaction between EndRegion and storage - // instructions, but this should all run after borrowck). + // These are all nops in a landing pad } StatementKind::Assign(Place::Local(_), box Rvalue::Use(_)) => { diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 8f026c706fd..f852195b835 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -161,7 +161,6 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | mir::StatementKind::InlineAsm { .. } | - mir::StatementKind::EndRegion(_) | mir::StatementKind::Retag { .. } | mir::StatementKind::EscapeToRaw { .. } | mir::StatementKind::AscribeUserType(..) | diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index 68840ed4a48..fb37f03a1cc 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -83,7 +83,6 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { self.record(match statement.kind { StatementKind::Assign(..) => "StatementKind::Assign", StatementKind::FakeRead(..) => "StatementKind::FakeRead", - StatementKind::EndRegion(..) => "StatementKind::EndRegion", StatementKind::Retag { .. } => "StatementKind::Retag", StatementKind::EscapeToRaw { .. } => "StatementKind::EscapeToRaw", StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant", diff --git a/src/test/mir-opt/end_region_1.rs b/src/test/mir-opt/end_region_1.rs deleted file mode 100644 index dd1c2bd5126..00000000000 --- a/src/test/mir-opt/end_region_1.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z identify_regions -Z emit-end-regions -// ignore-tidy-linelength - -// This is just about the simplest program that exhibits an EndRegion. - -fn main() { - let a = 3; - let b = &a; -} - -// END RUST SOURCE -// START rustc.main.SimplifyCfg-qualify-consts.after.mir -// let mut _0: (); -// ... -// let _2: &'11_1rs i32; -// ... -// let _1: i32; -// ... -// bb0: { -// StorageLive(_1); -// _1 = const 3i32; -// FakeRead(ForLet, _1); -// StorageLive(_2); -// _2 = &'11_1rs _1; -// FakeRead(ForLet, _2); -// _0 = (); -// EndRegion('11_1rs); -// StorageDead(_2); -// StorageDead(_1); -// return; -// } -// END rustc.main.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_2.rs b/src/test/mir-opt/end_region_2.rs deleted file mode 100644 index 6b0a28b8110..00000000000 --- a/src/test/mir-opt/end_region_2.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z identify_regions -Z emit-end-regions -// ignore-tidy-linelength - -// We will EndRegion for borrows in a loop that occur before break but -// not those after break. - -fn main() { - loop { - let a = true; - let b = &a; - if a { break; } - let c = &a; - } -} - -// END RUST SOURCE -// START rustc.main.SimplifyCfg-qualify-consts.after.mir -// let mut _0: (); -// ... -// let _7: &'26_3rs bool; -// ... -// let _3: &'26_1rs bool; -// ... -// let _2: bool; -// ... -// let mut _4: (); -// let mut _5: bool; -// ... -// bb0: { -// goto -> bb1; -// } -// bb1: { -// falseUnwind -> [real: bb2, cleanup: bb3]; -// } -// bb2: { -// StorageLive(_2); -// _2 = const true; -// FakeRead(ForLet, _2); -// StorageLive(_3); -// _3 = &'26_1rs _2; -// FakeRead(ForLet, _3); -// StorageLive(_5); -// _5 = _2; -// switchInt(move _5) -> [false: bb5, otherwise: bb4]; -// } -// bb3: { -// ... -// } -// bb4: { -// _0 = (); -// StorageDead(_5); -// EndRegion('26_1rs); -// StorageDead(_3); -// StorageDead(_2); -// return; -// } -// bb5: { -// _4 = (); -// StorageDead(_5); -// StorageLive(_7); -// _7 = &'26_3rs _2; -// FakeRead(ForLet, _7); -// _1 = (); -// EndRegion('26_3rs); -// StorageDead(_7); -// EndRegion('26_1rs); -// StorageDead(_3); -// StorageDead(_2); -// goto -> bb1; -// } -// END rustc.main.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_3.rs b/src/test/mir-opt/end_region_3.rs deleted file mode 100644 index d8d48358e53..00000000000 --- a/src/test/mir-opt/end_region_3.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z identify_regions -Z emit-end-regions -// ignore-tidy-linelength - -// Binding the borrow's subject outside the loop does not increase the -// scope of the borrow. - -fn main() { - let mut a; - loop { - a = true; - let b = &a; - if a { break; } - let c = &a; - } -} - -// END RUST SOURCE -// START rustc.main.SimplifyCfg-qualify-consts.after.mir -// let mut _0: (); -// ... -// let _7: &'30_3rs bool; -// ... -// let _3: &'30_1rs bool; -// ... -// let mut _1: bool; -// ... -// let mut _2: (); -// let mut _4: (); -// let mut _5: bool; -// let mut _6: !; -// bb0: { -// StorageLive(_1); -// goto -> bb1; -// } -// bb1: { -// falseUnwind -> [real: bb2, cleanup: bb3]; -// } -// bb2: { -// _1 = const true; -// StorageLive(_3); -// _3 = &'30_1rs _1; -// FakeRead(ForLet, _3); -// StorageLive(_5); -// _5 = _1; -// switchInt(move _5) -> [false: bb5, otherwise: bb4]; -// } -// bb3: { -// ... -// } -// bb4: { -// _0 = (); -// StorageDead(_5); -// EndRegion('30_1rs); -// StorageDead(_3); -// StorageDead(_1); -// return; -// } -// bb5: { -// _4 = (); -// StorageDead(_5); -// StorageLive(_7); -// _7 = &'30_3rs _1; -// FakeRead(ForLet, _7); -// _2 = (); -// EndRegion('30_3rs); -// StorageDead(_7); -// EndRegion('30_1rs); -// StorageDead(_3); -// goto -> bb1; -// } -// END rustc.main.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_4.rs b/src/test/mir-opt/end_region_4.rs deleted file mode 100644 index 3d15f20bd05..00000000000 --- a/src/test/mir-opt/end_region_4.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z identify_regions -Z emit-end-regions -// ignore-tidy-linelength - -// Unwinding should EndRegion for in-scope borrows: Direct borrows. - -fn main() { - let d = D(0); - let a = 0; - let b = &a; - foo(*b); - let c = &a; -} - -struct D(i32); -impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } - -fn foo(i: i32) { - if i > 0 { panic!("im positive"); } -} - -// END RUST SOURCE -// START rustc.main.SimplifyCfg-qualify-consts.after.mir -// let mut _0: (); -// ... -// let _6: &'31_4rs i32; -// ... -// let _3: &'31_2rs i32; -// ... -// let _2: i32; -// ... -// let _1: D; -// ... -// let mut _4: (); -// let mut _5: i32; -// bb0: { -// StorageLive(_1); -// _1 = D(const 0i32,); -// FakeRead(ForLet, _1); -// StorageLive(_2); -// _2 = const 0i32; -// FakeRead(ForLet, _2); -// StorageLive(_3); -// _3 = &'31_2rs _2; -// FakeRead(ForLet, _3); -// StorageLive(_5); -// _5 = (*_3); -// _4 = const foo(move _5) -> [return: bb2, unwind: bb3]; -// } -// bb1: { -// resume; -// } -// bb2: { -// StorageDead(_5); -// StorageLive(_6); -// _6 = &'31_4rs _2; -// FakeRead(ForLet, _6); -// _0 = (); -// EndRegion('31_4rs); -// StorageDead(_6); -// EndRegion('31_2rs); -// StorageDead(_3); -// StorageDead(_2); -// drop(_1) -> [return: bb4, unwind: bb1]; -// } -// bb3: { -// EndRegion('31_2rs); -// drop(_1) -> bb1; -// } -// bb4: { -// StorageDead(_1); -// return; -// } -// END rustc.main.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_5.rs b/src/test/mir-opt/end_region_5.rs deleted file mode 100644 index 06d1fbabe16..00000000000 --- a/src/test/mir-opt/end_region_5.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions - -// Unwinding should EndRegion for in-scope borrows: Borrowing via by-ref closure. - -fn main() { - let d = D(0); - foo(|| -> i32 { d.0 }); -} - -struct D(i32); -impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } - -fn foo(f: F) where F: FnOnce() -> i32 { - if f() > 0 { panic!("im positive"); } -} - -// END RUST SOURCE -// START rustc.main.SimplifyCfg-qualify-consts.after.mir -// fn main() -> () { -// ... -// let mut _0: (); -// ... -// let _1: D; -// ... -// let mut _2: (); -// let mut _3: [closure@NodeId(28) d:&'18s D]; -// let mut _4: &'18s D; -// bb0: { -// StorageLive(_1); -// _1 = D(const 0i32,); -// FakeRead(ForLet, _1); -// StorageLive(_3); -// StorageLive(_4); -// _4 = &'18s _1; -// _3 = [closure@NodeId(28)] { d: move _4 }; -// StorageDead(_4); -// _2 = const foo(move _3) -> [return: bb2, unwind: bb3]; -// } -// bb1: { -// resume; -// } -// bb2: { -// EndRegion('18s); -// StorageDead(_3); -// _0 = (); -// drop(_1) -> [return: bb4, unwind: bb1]; -// } -// bb3: { -// EndRegion('18s); -// drop(_1) -> bb1; -// } -// bb4: { -// StorageDead(_1); -// return; -// } -// } -// END rustc.main.SimplifyCfg-qualify-consts.after.mir - -// START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(28) d:&'18s D]) -> i32 { -// let mut _0: i32; -// -// bb0: { -// _0 = ((*(_1.0: &'18s D)).0: i32); -// return; -// } -// END rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_6.rs b/src/test/mir-opt/end_region_6.rs deleted file mode 100644 index d0db23e6de0..00000000000 --- a/src/test/mir-opt/end_region_6.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions -// ignore-tidy-linelength - -// Unwinding should EndRegion for in-scope borrows: 2nd borrow within by-ref closure. - -fn main() { - let d = D(0); - foo(|| -> i32 { let r = &d; r.0 }); -} - -struct D(i32); -impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } - -fn foo(f: F) where F: FnOnce() -> i32 { - if f() > 0 { panic!("im positive"); } -} - -// END RUST SOURCE -// START rustc.main.SimplifyCfg-qualify-consts.after.mir -// fn main() -> () { -// let mut _0: (); -// ... -// let _1: D; -// ... -// let mut _2: (); -// let mut _3: [closure@NodeId(33) d:&'24s D]; -// let mut _4: &'24s D; -// bb0: { -// StorageLive(_1); -// _1 = D(const 0i32,); -// FakeRead(ForLet, _1); -// StorageLive(_3); -// StorageLive(_4); -// _4 = &'24s _1; -// _3 = [closure@NodeId(33)] { d: move _4 }; -// StorageDead(_4); -// _2 = const foo(move _3) -> [return: bb2, unwind: bb3]; -// } -// bb1: { -// resume; -// } -// bb2: { -// EndRegion('24s); -// StorageDead(_3); -// _0 = (); -// drop(_1) -> [return: bb4, unwind: bb1]; -// } -// bb3: { -// EndRegion('24s); -// drop(_1) -> bb1; -// } -// bb4: { -// StorageDead(_1); -// return; -// } -// END rustc.main.SimplifyCfg-qualify-consts.after.mir - -// START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(33) d:&'24s D]) -> i32 { -// let mut _0: i32; -// ... -// let _2: &'21_0rs D; -// ... -// bb0: { -// StorageLive(_2); -// _2 = &'21_0rs (*(_1.0: &'24s D)); -// FakeRead(ForLet, _2); -// _0 = ((*_2).0: i32); -// EndRegion('21_0rs); -// StorageDead(_2); -// return; -// } -// END rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_7.rs b/src/test/mir-opt/end_region_7.rs deleted file mode 100644 index c7df440ebe2..00000000000 --- a/src/test/mir-opt/end_region_7.rs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions -// ignore-tidy-linelength - -// Unwinding should EndRegion for in-scope borrows: Borrow of moved data. - -fn main() { - let d = D(0); - foo(move || -> i32 { let r = &d; r.0 }); -} - -struct D(i32); -impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } - -fn foo(f: F) where F: FnOnce() -> i32 { - if f() > 0 { panic!("im positive"); } -} - -// END RUST SOURCE -// START rustc.main.SimplifyCfg-qualify-consts.after.mir -// fn main() -> () { -// let mut _0: (); -// ... -// let _1: D; -// ... -// let mut _2: (); -// let mut _3: [closure@NodeId(33) d:D]; -// bb0: { -// StorageLive(_1); -// _1 = D(const 0i32,); -// FakeRead(ForLet, _1); -// StorageLive(_3); -// _3 = [closure@NodeId(33)] { d: move _1 }; -// _2 = const foo(move _3) -> [return: bb2, unwind: bb4]; -// } -// bb1: { -// resume; -// } -// bb2: { -// drop(_3) -> [return: bb5, unwind: bb3]; -// } -// bb3: { -// drop(_1) -> bb1; -// } -// bb4: { -// drop(_3) -> bb3; -// } -// bb5: { -// StorageDead(_3); -// _0 = (); -// drop(_1) -> [return: bb6, unwind: bb1]; -// } -// bb6: { -// StorageDead(_1); -// return; -// } -// } -// END rustc.main.SimplifyCfg-qualify-consts.after.mir - -// START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(33) d:D]) -> i32 { -// let mut _0: i32; -// ... -// let _2: &'21_0rs D; -// ... -// bb0: { -// StorageLive(_2); -// _2 = &'21_0rs (_1.0: D); -// FakeRead(ForLet, _2); -// _0 = ((*_2).0: i32); -// EndRegion('21_0rs); -// StorageDead(_2); -// drop(_1) -> [return: bb2, unwind: bb1]; -// } -// bb1: { -// resume; -// } -// bb2: { -// return; -// } -// } -// END rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_8.rs b/src/test/mir-opt/end_region_8.rs deleted file mode 100644 index 9f2a9c3b72e..00000000000 --- a/src/test/mir-opt/end_region_8.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions -// ignore-tidy-linelength - -// Unwinding should EndRegion for in-scope borrows: Move of borrow into closure. - -fn main() { - let d = D(0); - let r = &d; - foo(move || -> i32 { r.0 }); -} - -struct D(i32); -impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } - -fn foo(f: F) where F: FnOnce() -> i32 { - if f() > 0 { panic!("im positive"); } -} - -// END RUST SOURCE -// START rustc.main.SimplifyCfg-qualify-consts.after.mir -// fn main() -> () { -// let mut _0: (); -// ... -// let _2: &'26_1rs D; -// ... -// let _1: D; -// ... -// let mut _3: (); -// let mut _4: [closure@NodeId(33) r:&'24s D]; -// bb0: { -// StorageLive(_1); -// _1 = D(const 0i32,); -// FakeRead(ForLet, _1); -// StorageLive(_2); -// _2 = &'26_1rs _1; -// FakeRead(ForLet, _2); -// StorageLive(_4); -// _4 = [closure@NodeId(33)] { r: _2 }; -// _3 = const foo(move _4) -> [return: bb2, unwind: bb3]; -// } -// bb1: { -// resume; -// } -// bb2: { -// EndRegion('24s); -// StorageDead(_4); -// _0 = (); -// EndRegion('26_1rs); -// StorageDead(_2); -// drop(_1) -> [return: bb4, unwind: bb1]; -// } -// bb3: { -// EndRegion('24s); -// EndRegion('26_1rs); -// drop(_1) -> bb1; -// } -// bb4: { -// StorageDead(_1); -// return; -// } -// } -// END rustc.main.SimplifyCfg-qualify-consts.after.mir - -// START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(33) r:&'24s D]) -> i32 { -// let mut _0: i32; -// -// bb0: { -// _0 = ((*(_1.0: &'26_1rs D)).0: i32); -// return; -// } -// } -// END rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_9.rs b/src/test/mir-opt/end_region_9.rs deleted file mode 100644 index ef2d949d307..00000000000 --- a/src/test/mir-opt/end_region_9.rs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions -// ignore-tidy-linelength - -// This test models a scenario that arielb1 found during review. -// Namely, any filtering of EndRegions must ensure to continue to emit -// any necessary EndRegions that occur earlier in the source than the -// first borrow involving that region. -// -// It is tricky to actually construct examples of this, which is the -// main reason that I am keeping this test even though I have now -// removed the pre-filter that motivated the test in the first place. - -fn main() { - let mut second_iter = false; - let x = 3; - 'a: loop { - let mut y; - loop { - if second_iter { - break 'a; // want to generate `EndRegion('a)` here - } else { - y = &/*'a*/ x; - } - second_iter = true; - } - } -} - -// END RUST SOURCE -// START rustc.main.SimplifyCfg-qualify-consts.after.mir -// fn main() -> () { -// let mut _0: (); -// ... -// let mut _4: &'37_0rs i32; -// ... -// let _2: i32; -// ... -// let mut _1: bool; -// ... -// let mut _3: (); -// let mut _5: !; -// let mut _6: (); -// let mut _7: bool; -// let mut _8: !; -// bb0: { -// StorageLive(_1); -// _1 = const false; -// FakeRead(ForLet, _1); -// StorageLive(_2); -// _2 = const 3i32; -// FakeRead(ForLet, _2); -// falseUnwind -> [real: bb2, cleanup: bb1]; -// } -// bb1: { -// ... -// } -// bb2: { -// StorageLive(_4); -// goto -> bb3; -// } -// bb3: { -// falseUnwind -> [real: bb4, cleanup: bb1]; -// } -// bb4: { -// StorageLive(_7); -// _7 = _1; -// switchInt(move _7) -> [false: bb6, otherwise: bb5]; -// } -// bb5: { -// _0 = (); -// StorageDead(_7); -// EndRegion('37_0rs); -// StorageDead(_4); -// StorageDead(_2); -// StorageDead(_1); -// return; -// } -// bb6: { -// _4 = &'37_0rs _2; -// _6 = (); -// StorageDead(_7); -// _1 = const true; -// _3 = (); -// goto -> bb3; -// } -// } -// END rustc.main.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_cyclic.rs b/src/test/mir-opt/end_region_cyclic.rs deleted file mode 100644 index 3dbc73caf65..00000000000 --- a/src/test/mir-opt/end_region_cyclic.rs +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions -// ignore-tidy-linelength - -// This test models a scenario with a cyclic reference. Rust obviously -// needs to handle such cases. -// -// The interesting part about this test is that such case shows that -// one cannot generally force all references to be dead before you hit -// their EndRegion; at least, not without breaking the more important -// property that all borrowed storage locations have their regions -// ended strictly before their StorageDeads. (This test was inspired -// by discussion on Issue #43481.) - -use std::cell::Cell; - -struct S<'a> { - r: Cell>>, -} - -fn main() { - loop { - let x = S { r: Cell::new(None) }; - x.r.set(Some(&x)); - if query() { break; } - x.r.set(Some(&x)); - } -} - -fn query() -> bool { true } - -// END RUST SOURCE -// START rustc.main.SimplifyCfg-qualify-consts.after.mir -// fn main() -> (){ -// let mut _0: (); -// scope 1 { -// } -// scope 2 { -// let _2: S<'49_0rs>; -// } -// let mut _1: (); -// let mut _3: std::cell::Cell>>; -// let mut _4: std::option::Option<&'49_0rs S<'49_0rs>>; -// let mut _5: (); -// let mut _6: &'25s std::cell::Cell>>; -// let mut _7: std::option::Option<&'49_0rs S<'49_0rs>>; -// let mut _8: &'49_0rs S<'49_0rs>; -// let mut _9: &'49_0rs S<'49_0rs>; -// let mut _10: (); -// let mut _11: bool; -// let mut _12: !; -// let mut _13: (); -// let mut _14: &'47s std::cell::Cell>>; -// let mut _15: std::option::Option<&'49_0rs S<'49_0rs>>; -// let mut _16: &'49_0rs S<'49_0rs>; -// let mut _17: &'49_0rs S<'49_0rs>; -// bb0: { -// goto -> bb1; -// } -// bb1: { -// falseUnwind -> [real: bb2, cleanup: bb3]; -// } -// bb2: { -// StorageLive(_2); -// StorageLive(_3); -// StorageLive(_4); -// _4 = std::option::Option<&'49_0rs S<'49_0rs>>::None; -// _3 = const >::new(move _4) -> [return: bb4, unwind: bb3]; -// } -// bb3: { -// resume; -// } -// bb4: { -// StorageDead(_4); -// _2 = S<'49_0rs> { r: move _3 }; -// StorageDead(_3); -// FakeRead(ForLet, _2); -// StorageLive(_6); -// _6 = &'25s (_2.0: std::cell::Cell>>); -// StorageLive(_7); -// StorageLive(_8); -// StorageLive(_9); -// _9 = &'49_0rs _2; -// _8 = &'49_0rs (*_9); -// _7 = std::option::Option<&'49_0rs S<'49_0rs>>::Some(move _8,); -// StorageDead(_8); -// _5 = const >::set(move _6, move _7) -> [return: bb5, unwind: bb3]; -// } -// bb5: { -// EndRegion('25s); -// StorageDead(_7); -// StorageDead(_6); -// StorageDead(_9); -// StorageLive(_11); -// _11 = const query() -> [return: bb6, unwind: bb3]; -// } -// bb6: { -// switchInt(move _11) -> [false: bb8, otherwise: bb7]; -// } -// bb7: { -// _0 = (); -// StorageDead(_11); -// EndRegion('49_0rs); -// StorageDead(_2); -// return; -// } -// bb8: { -// _10 = (); -// StorageDead(_11); -// StorageLive(_14); -// _14 = &'47s (_2.0: std::cell::Cell>>); -// StorageLive(_15); -// StorageLive(_16); -// StorageLive(_17); -// _17 = &'49_0rs _2; -// _16 = &'49_0rs (*_17); -// _15 = std::option::Option<&'49_0rs S<'49_0rs>>::Some(move _16,); -// StorageDead(_16); -// _13 = const >::set(move _14, move _15) -> [return: bb9, unwind: bb3]; -// } -// bb9: { -// EndRegion('47s); -// StorageDead(_15); -// StorageDead(_14); -// StorageDead(_17); -// _1 = (); -// EndRegion('49_0rs); -// StorageDead(_2); -// goto -> bb1; -// } -// } -// END rustc.main.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_destruction_extents_1.rs b/src/test/mir-opt/end_region_destruction_extents_1.rs deleted file mode 100644 index eb381dfc552..00000000000 --- a/src/test/mir-opt/end_region_destruction_extents_1.rs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions -// ignore-tidy-linelength - -// A scenario with significant destruction code extents (which have -// suffix "dce" in current `-Z identify_regions` rendering). - -#![feature(dropck_eyepatch)] - -fn main() { - // Since the second param to `D1` is may_dangle, it is legal for - // the region of that parameter to end before the drop code for D1 - // is executed. - (D1(&S1("ex1"), &S1("dang1"))).0; -} - -#[derive(Debug)] -struct S1(&'static str); - -#[derive(Debug)] -struct D1<'a, 'b>(&'a S1, &'b S1); - -// The `#[may_dangle]` means that references of type `&'b _` may be -// invalid during the execution of this destructor; i.e. in this case -// the destructor code is not allowed to read or write `*self.1`, while -// it can read/write `*self.0`. -unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { - fn drop(&mut self) { - println!("D1({:?}, _)", self.0); - } -} - -// Notes on the MIR output below: -// -// 1. The `EndRegion('13s)` is allowed to precede the `drop(_3)` -// solely because of the #[may_dangle] mentioned above. -// -// 2. Regarding the occurrence of `EndRegion('15ds)` *after* `StorageDead(_6)` -// (where we have borrows `&'15ds _6`): Eventually: -// -// i. this code should be rejected (by mir-borrowck), or -// -// ii. the MIR code generation should be changed so that the -// EndRegion('15ds)` precedes `StorageDead(_6)` in the -// control-flow. (Note: arielb1 views drop+storagedead as one -// unit, and does not see this option as a useful avenue to -// explore.), or -// -// iii. the presence of EndRegion should be made irrelevant by a -// transformation encoding the effects of rvalue-promotion. -// This may be the simplest and most-likely option; note in -// particular that `StorageDead(_6)` goes away below in -// rustc.main.QualifyAndPromoteConstants.after.mir - -// END RUST SOURCE - -// START rustc.main.QualifyAndPromoteConstants.before.mir -// fn main() -> () { -// let mut _0: (); -// let mut _1: &'15ds S1; -// let mut _2: D1<'15ds, '13s>; -// let mut _3: &'15ds S1; -// let mut _4: &'15ds S1; -// let _5: S1; -// let mut _6: &'13s S1; -// let mut _7: &'13s S1; -// let _8: S1; -// bb0: { -// StorageLive(_2); -// StorageLive(_3); -// StorageLive(_4); -// StorageLive(_5); -// _5 = S1(const "ex1",); -// _4 = &'15ds _5; -// _3 = &'15ds (*_4); -// StorageLive(_6); -// StorageLive(_7); -// StorageLive(_8); -// _8 = S1(const "dang1",); -// _7 = &'13s _8; -// _6 = &'13s (*_7); -// _2 = D1<'15ds, '13s>(move _3, move _6); -// EndRegion('13s); -// StorageDead(_6); -// StorageDead(_3); -// _1 = (_2.0: &'15ds S1); -// drop(_2) -> [return: bb2, unwind: bb1]; -// } -// bb1: { -// resume; -// } -// bb2: { -// StorageDead(_2); -// StorageDead(_7); -// StorageDead(_8); -// StorageDead(_4); -// StorageDead(_5); -// EndRegion('15ds); -// _0 = (); -// return; -// } -// } -// END rustc.main.QualifyAndPromoteConstants.before.mir - -// START rustc.main.QualifyAndPromoteConstants.after.mir -// fn main() -> (){ -// let mut _0: (); -// let mut _1: &'15ds S1; -// let mut _2: D1<'15ds, '13s>; -// let mut _3: &'15ds S1; -// let mut _4: &'15ds S1; -// let _5: S1; -// let mut _6: &'13s S1; -// let mut _7: &'13s S1; -// let _8: S1; -// bb0: { -// StorageLive(_2); -// StorageLive(_3); -// StorageLive(_4); -// _4 = &'15ds (promoted[1]: S1); -// _3 = &'15ds (*_4); -// StorageLive(_6); -// StorageLive(_7); -// _7 = &'13s (promoted[0]: S1); -// _6 = &'13s (*_7); -// _2 = D1<'15ds, '13s>(move _3, move _6); -// EndRegion('13s); -// StorageDead(_6); -// StorageDead(_3); -// _1 = (_2.0: &'15ds S1); -// drop(_2) -> [return: bb2, unwind: bb1]; -// } -// bb1: { -// resume; -// } -// bb2: { -// StorageDead(_2); -// StorageDead(_7); -// StorageDead(_4); -// EndRegion('15ds); -// _0 = (); -// return; -// } -// } -// END rustc.main.QualifyAndPromoteConstants.after.mir diff --git a/src/test/mir-opt/issue-43457.rs b/src/test/mir-opt/issue-43457.rs deleted file mode 100644 index 85cecc5070c..00000000000 --- a/src/test/mir-opt/issue-43457.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions -// ignore-tidy-linelength - -// Regression test for #43457: an `EndRegion` was missing from output -// because compiler was using a faulty means for region map lookup. - -use std::cell::RefCell; - -fn rc_refcell_test(r: RefCell) { - r.borrow_mut(); -} - -fn main() { } - -// END RUST SOURCE -// START rustc.rc_refcell_test.SimplifyCfg-qualify-consts.after.mir -// -// fn rc_refcell_test(_1: std::cell::RefCell) -> () { -// let mut _0: (); -// scope 1 { -// let _2: std::cell::RefCell; -// } -// let mut _3: std::cell::RefMut<'17ds, i32>; -// let mut _4: &'17ds std::cell::RefCell; -// -// bb0: { -// StorageLive(_2); -// _2 = _1; -// StorageLive(_4); -// _4 = &'17ds _2; -// _3 = const >::borrow_mut(_4) -> bb1; -// } -// -// bb1: { -// drop(_3) -> bb2; -// } -// -// bb2: { -// StorageDead(_4); -// EndRegion('17ds); -// _0 = (); -// StorageDead(_2); -// return; -// } -// } diff --git a/src/test/mir-opt/loop_test.rs b/src/test/mir-opt/loop_test.rs index 2e526a221cc..77616f1d39a 100644 --- a/src/test/mir-opt/loop_test.rs +++ b/src/test/mir-opt/loop_test.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z identify_regions -Z emit-end-regions +// compile-flags: -Z identify_regions // Tests to make sure we correctly generate falseUnwind edges in loops diff --git a/src/test/run-pass/issues/issue-16671.rs b/src/test/run-pass/issues/issue-16671.rs index 5ff2bc97ae2..14bda56dd8f 100644 --- a/src/test/run-pass/issues/issue-16671.rs +++ b/src/test/run-pass/issues/issue-16671.rs @@ -9,7 +9,7 @@ // except according to those terms. // run-pass -//compile-flags: -Z borrowck=compare -Z emit-end-regions +//compile-flags: -Z borrowck=compare #![deny(warnings)] diff --git a/src/test/ui/borrowck/immutable-arg.rs b/src/test/ui/borrowck/immutable-arg.rs index 7c387ed0808..c5291ab3e1d 100644 --- a/src/test/ui/borrowck/immutable-arg.rs +++ b/src/test/ui/borrowck/immutable-arg.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//compile-flags: -Z emit-end-regions -Z borrowck=compare +//compile-flags: -Z borrowck=compare fn foo(_x: u32) { _x = 4; diff --git a/src/test/ui/issues/issue-45697-1.rs b/src/test/ui/issues/issue-45697-1.rs index b8be209833a..e79bfb23b05 100644 --- a/src/test/ui/issues/issue-45697-1.rs +++ b/src/test/ui/issues/issue-45697-1.rs @@ -11,7 +11,7 @@ // Test that assignments to an `&mut` pointer which is found in a // borrowed (but otherwise non-aliasable) location is illegal. -// compile-flags: -Z emit-end-regions -Z borrowck=compare -C overflow-checks=on +// compile-flags: -Z borrowck=compare -C overflow-checks=on struct S<'a> { pointer: &'a mut isize diff --git a/src/test/ui/issues/issue-45697.rs b/src/test/ui/issues/issue-45697.rs index 27acc2c89f7..936e8a40fa8 100644 --- a/src/test/ui/issues/issue-45697.rs +++ b/src/test/ui/issues/issue-45697.rs @@ -11,7 +11,7 @@ // Test that assignments to an `&mut` pointer which is found in a // borrowed (but otherwise non-aliasable) location is illegal. -// compile-flags: -Z emit-end-regions -Z borrowck=compare -C overflow-checks=off +// compile-flags: -Z borrowck=compare -C overflow-checks=off struct S<'a> { pointer: &'a mut isize diff --git a/src/test/ui/issues/issue-46023.rs b/src/test/ui/issues/issue-46023.rs index d5c8cd6d0f8..ea7e627eadf 100644 --- a/src/test/ui/issues/issue-46023.rs +++ b/src/test/ui/issues/issue-46023.rs @@ -9,7 +9,7 @@ // except according to those terms. // revisions: ast mir -//[mir]compile-flags: -Z emit-end-regions -Z borrowck=mir +//[mir]compile-flags: -Z borrowck=mir fn main() { let x = 0; diff --git a/src/test/ui/issues/issue-46471-1.rs b/src/test/ui/issues/issue-46471-1.rs index 0dbcdea89f9..7fb77f9ce8b 100644 --- a/src/test/ui/issues/issue-46471-1.rs +++ b/src/test/ui/issues/issue-46471-1.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z emit-end-regions -Z borrowck=compare +// compile-flags: -Z borrowck=compare fn main() { let y = { diff --git a/src/test/ui/issues/issue-46471.rs b/src/test/ui/issues/issue-46471.rs index 654a3d8f964..201b8e2de9a 100644 --- a/src/test/ui/issues/issue-46471.rs +++ b/src/test/ui/issues/issue-46471.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z emit-end-regions -Z borrowck=compare +// compile-flags: -Z borrowck=compare fn foo() -> &'static u32 { let x = 0; diff --git a/src/test/ui/issues/issue-46472.rs b/src/test/ui/issues/issue-46472.rs index 8137cd2dd89..b6838a48b1b 100644 --- a/src/test/ui/issues/issue-46472.rs +++ b/src/test/ui/issues/issue-46472.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z emit-end-regions -Z borrowck=compare +// compile-flags: -Z borrowck=compare fn bar<'a>() -> &'a mut u32 { &mut 4 diff --git a/src/test/ui/moves/moves-based-on-type-tuple.rs b/src/test/ui/moves/moves-based-on-type-tuple.rs index 27903fee117..9dda275d95e 100644 --- a/src/test/ui/moves/moves-based-on-type-tuple.rs +++ b/src/test/ui/moves/moves-based-on-type-tuple.rs @@ -10,7 +10,7 @@ #![feature(box_syntax)] -// compile-flags: -Z emit-end-regions -Z borrowck=compare +// compile-flags: -Z borrowck=compare fn dup(x: Box) -> Box<(Box,Box)> { box (x, x) diff --git a/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs b/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs index ae815a5efe9..f96e73ce09f 100644 --- a/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs +++ b/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z emit-end-regions -Zborrowck=mir +// compile-flags: -Zborrowck=mir // compile-pass #![allow(warnings)] diff --git a/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs b/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs index 00d146e0f02..0e9cdf2f428 100644 --- a/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs +++ b/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//compile-flags: -Z emit-end-regions -Zborrowck=mir +//compile-flags: -Zborrowck=mir #![allow(warnings)] diff --git a/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs index cd46014a7f5..080fdfe0228 100644 --- a/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs +++ b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//compile-flags: -Z emit-end-regions -Zborrowck=mir +//compile-flags: -Zborrowck=mir #![allow(warnings)] diff --git a/src/test/ui/nll/maybe-initialized-drop.rs b/src/test/ui/nll/maybe-initialized-drop.rs index 9a3aca34620..db680ef8bea 100644 --- a/src/test/ui/nll/maybe-initialized-drop.rs +++ b/src/test/ui/nll/maybe-initialized-drop.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//compile-flags: -Z emit-end-regions -Zborrowck=mir +//compile-flags: -Zborrowck=mir #![allow(warnings)] From 6027e0810ff9f60103d2ff4c24791e40db491316 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 10 Nov 2018 23:52:20 +0000 Subject: [PATCH 0052/1984] Only handle ReVar regions in NLL borrowck Now that lexical MIR borrowck is gone, there's no need to store Regions unnecessarily. --- src/librustc_mir/borrow_check/borrow_set.rs | 28 +++--- src/librustc_mir/borrow_check/mod.rs | 7 +- .../borrow_check/nll/explain_borrow/mod.rs | 2 +- src/librustc_mir/dataflow/impls/borrows.rs | 91 ++----------------- 4 files changed, 23 insertions(+), 105 deletions(-) diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index c432826dca8..fd7dc7fc4bd 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -9,6 +9,7 @@ // except according to those terms. use borrow_check::place_ext::PlaceExt; +use borrow_check::nll::ToRegionVid; use dataflow::indexes::BorrowIndex; use dataflow::move_paths::MoveData; use rustc::mir::traversal; @@ -16,7 +17,7 @@ use rustc::mir::visit::{ PlaceContext, Visitor, NonUseContext, MutatingUseContext, NonMutatingUseContext }; use rustc::mir::{self, Location, Mir, Place, Local}; -use rustc::ty::{Region, TyCtxt}; +use rustc::ty::{RegionVid, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::bit_set::BitSet; @@ -42,7 +43,7 @@ crate struct BorrowSet<'tcx> { /// Every borrow has a region; this maps each such regions back to /// its borrow-indexes. - crate region_map: FxHashMap, FxHashSet>, + crate region_map: FxHashMap>, /// Map from local to all the borrows on that local crate local_map: FxHashMap>, @@ -77,7 +78,7 @@ crate struct BorrowData<'tcx> { /// What kind of borrow this is crate kind: mir::BorrowKind, /// The region for which this borrow is live - crate region: Region<'tcx>, + crate region: RegionVid, /// Place from which we are borrowing crate borrowed_place: mir::Place<'tcx>, /// Place to which the borrow was stored @@ -92,13 +93,7 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> { mir::BorrowKind::Unique => "uniq ", mir::BorrowKind::Mut { .. } => "mut ", }; - let region = self.region.to_string(); - let separator = if !region.is_empty() { - " " - } else { - "" - }; - write!(w, "&{}{}{}{:?}", region, separator, kind, self.borrowed_place) + write!(w, "&{:?} {}{:?}", self.region, kind, self.borrowed_place) } } @@ -189,7 +184,7 @@ struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> { idx_vec: IndexVec>, location_map: FxHashMap, activation_map: FxHashMap>, - region_map: FxHashMap, FxHashSet>, + region_map: FxHashMap>, local_map: FxHashMap>, /// When we encounter a 2-phase borrow statement, it will always @@ -219,6 +214,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { return; } + let region = region.to_region_vid(); + let borrow = BorrowData { kind, region, @@ -230,7 +227,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { let idx = self.idx_vec.push(borrow); self.location_map.insert(location, idx); - self.insert_as_pending_if_two_phase(location, &assigned_place, region, kind, idx); + self.insert_as_pending_if_two_phase(location, &assigned_place, kind, idx); self.region_map.entry(region).or_default().insert(idx); if let Some(local) = borrowed_place.root_local() { @@ -314,7 +311,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { let borrow_data = &self.idx_vec[borrow_index]; assert_eq!(borrow_data.reserve_location, location); assert_eq!(borrow_data.kind, kind); - assert_eq!(borrow_data.region, region); + assert_eq!(borrow_data.region, region.to_region_vid()); assert_eq!(borrow_data.borrowed_place, *place); } @@ -347,13 +344,12 @@ impl<'a, 'gcx, 'tcx> GatherBorrows<'a, 'gcx, 'tcx> { &mut self, start_location: Location, assigned_place: &mir::Place<'tcx>, - region: Region<'tcx>, kind: mir::BorrowKind, borrow_index: BorrowIndex, ) { debug!( - "Borrows::insert_as_pending_if_two_phase({:?}, {:?}, {:?}, {:?})", - start_location, assigned_place, region, borrow_index, + "Borrows::insert_as_pending_if_two_phase({:?}, {:?}, {:?})", + start_location, assigned_place, borrow_index, ); if !self.allow_two_phase_borrow(kind) { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 8819908de6a..76ba6ae5de6 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -14,7 +14,6 @@ use borrow_check::nll::region_infer::RegionInferenceContext; use rustc::hir; use rustc::hir::Node; use rustc::hir::def_id::DefId; -use rustc::hir::map::definitions::DefPathData; use rustc::infer::InferCtxt; use rustc::lint::builtin::UNUSED_MUT; use rustc::middle::borrowck::SignalledError; @@ -162,10 +161,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( move_data: move_data, param_env: param_env, }; - let body_id = match tcx.def_key(def_id).disambiguated_data.data { - DefPathData::StructCtor | DefPathData::EnumVariant(_) => None, - _ => Some(tcx.hir.body_owned_by(id)), - }; let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len()); let mut flow_inits = FlowAtLocation::new(do_dataflow( @@ -212,7 +207,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( id, &attributes, &dead_unwinds, - Borrows::new(tcx, mir, regioncx.clone(), def_id, body_id, &borrow_set), + Borrows::new(tcx, mir, regioncx.clone(), &borrow_set), |rs, i| DebugFormatted::new(&rs.location(i)), )); let flow_uninits = FlowAtLocation::new(do_dataflow( diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index 2bf531d1d3e..bb9a29b055b 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -206,7 +206,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let mir = self.mir; let tcx = self.infcx.tcx; - let borrow_region_vid = regioncx.to_region_vid(borrow.region); + let borrow_region_vid = borrow.region; debug!( "explain_why_borrow_contains_point: borrow_region_vid={:?}", borrow_region_vid diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 5e84aa05d38..27bc28ac81d 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -12,18 +12,13 @@ use borrow_check::borrow_set::{BorrowSet, BorrowData}; use borrow_check::place_ext::PlaceExt; use rustc; -use rustc::hir; -use rustc::hir::def_id::DefId; -use rustc::middle::region; use rustc::mir::{self, Location, Place, Mir}; use rustc::ty::TyCtxt; -use rustc::ty::{RegionKind, RegionVid}; -use rustc::ty::RegionKind::ReScope; +use rustc::ty::RegionVid; use rustc_data_structures::bit_set::{BitSet, BitSetOperator}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; -use rustc_data_structures::sync::Lrc; use dataflow::{BitDenotation, BlockSets, InitialFlow}; pub use dataflow::indexes::BorrowIndex; @@ -42,8 +37,6 @@ use std::rc::Rc; pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, - scope_tree: Lrc, - root_scope: Option, borrow_set: Rc>, borrows_out_of_scope_at_location: FxHashMap>, @@ -150,18 +143,8 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, nonlexical_regioncx: Rc>, - def_id: DefId, - body_id: Option, borrow_set: &Rc>, ) -> Self { - let scope_tree = tcx.region_scope_tree(def_id); - let root_scope = body_id.map(|body_id| { - region::Scope { - id: tcx.hir.body(body_id).value.hir_id.local_id, - data: region::ScopeData::CallSite - } - }); - let mut borrows_out_of_scope_at_location = FxHashMap::default(); for (borrow_index, borrow_data) in borrow_set.borrows.iter_enumerated() { let borrow_region = borrow_data.region.to_region_vid(); @@ -177,8 +160,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { mir: mir, borrow_set: borrow_set.clone(), borrows_out_of_scope_at_location, - scope_tree, - root_scope, _nonlexical_regioncx: nonlexical_regioncx, } } @@ -277,22 +258,13 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { panic!("could not find BorrowIndex for location {:?}", location); }); - if let RegionKind::ReEmpty = region { - // If the borrowed value dies before the borrow is used, the region for - // the borrow can be empty. Don't track the borrow in that case. - debug!("Borrows::statement_effect_on_borrows \ - location: {:?} stmt: {:?} has empty region, killing {:?}", - location, stmt.kind, index); - sets.kill(*index); - return - } else { - debug!("Borrows::statement_effect_on_borrows location: {:?} stmt: {:?}", - location, stmt.kind); - } - - assert!(self.borrow_set.region_map.get(region).unwrap_or_else(|| { - panic!("could not find BorrowIndexs for region {:?}", region); - }).contains(&index)); + assert!(self.borrow_set.region_map + .get(®ion.to_region_vid()) + .unwrap_or_else(|| { + panic!("could not find BorrowIndexs for RegionVid {:?}", region); + }) + .contains(&index) + ); sets.gen(*index); // Issue #46746: Two-phase borrows handles @@ -349,52 +321,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { self.kill_loans_out_of_scope_at_location(sets, location); } - fn terminator_effect(&self, sets: &mut BlockSets, location: Location) { - debug!("Borrows::terminator_effect sets: {:?} location: {:?}", sets, location); - - let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| { - panic!("could not find block at location {:?}", location); - }); - - let term = block.terminator(); - match term.kind { - mir::TerminatorKind::Resume | - mir::TerminatorKind::Return | - mir::TerminatorKind::GeneratorDrop => { - // When we return from the function, then all `ReScope`-style regions - // are guaranteed to have ended. - // Normally, there would be `EndRegion` statements that come before, - // and hence most of these loans will already be dead -- but, in some cases - // like unwind paths, we do not always emit `EndRegion` statements, so we - // add some kills here as a "backup" and to avoid spurious error messages. - for (borrow_index, borrow_data) in self.borrow_set.borrows.iter_enumerated() { - if let ReScope(scope) = borrow_data.region { - // Check that the scope is not actually a scope from a function that is - // a parent of our closure. Note that the CallSite scope itself is - // *outside* of the closure, for some weird reason. - if let Some(root_scope) = self.root_scope { - if *scope != root_scope && - self.scope_tree.is_subscope_of(*scope, root_scope) - { - sets.kill(borrow_index); - } - } - } - } - } - mir::TerminatorKind::Abort | - mir::TerminatorKind::SwitchInt {..} | - mir::TerminatorKind::Drop {..} | - mir::TerminatorKind::DropAndReplace {..} | - mir::TerminatorKind::Call {..} | - mir::TerminatorKind::Assert {..} | - mir::TerminatorKind::Yield {..} | - mir::TerminatorKind::Goto {..} | - mir::TerminatorKind::FalseEdges {..} | - mir::TerminatorKind::FalseUnwind {..} | - mir::TerminatorKind::Unreachable => {} - } - } + fn terminator_effect(&self, _: &mut BlockSets, _: Location) {} fn propagate_call_return(&self, _in_out: &mut BitSet, From 1d7fc0ca500d8e532e7b1019397baec353560c26 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 17 Nov 2018 21:07:17 +0000 Subject: [PATCH 0053/1984] Simplify MIR drop generation Now that EndRegion is gone, we don't need to create as many gotos. --- src/librustc_mir/build/scope.rs | 288 ++++++++++++++++---------------- src/test/mir-opt/issue-49232.rs | 41 +---- 2 files changed, 154 insertions(+), 175 deletions(-) diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 1a8f8fbbb68..2a11f24095b 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -96,6 +96,7 @@ use rustc::hir::def_id::LOCAL_CRATE; use rustc::mir::*; use syntax_pos::{Span}; use rustc_data_structures::fx::FxHashMap; +use std::collections::hash_map::Entry; #[derive(Debug)] pub struct Scope<'tcx> { @@ -224,7 +225,7 @@ impl<'tcx> Scope<'tcx> { /// Should always be run for all inner scopes when a drop is pushed into some scope enclosing a /// larger extent of code. /// - /// `storage_only` controls whether to invalidate only drop paths run `StorageDead`. + /// `storage_only` controls whether to invalidate only drop paths that run `StorageDead`. /// `this_scope_only` controls whether to invalidate only drop paths that refer to the current /// top-of-scope (as opposed to dependent scopes). fn invalidate_cache(&mut self, storage_only: bool, this_scope_only: bool) { @@ -242,8 +243,8 @@ impl<'tcx> Scope<'tcx> { } if !storage_only && !this_scope_only { - for dropdata in &mut self.drops { - if let DropKind::Value { ref mut cached_block } = dropdata.kind { + for drop_data in &mut self.drops { + if let DropKind::Value { ref mut cached_block } = drop_data.kind { cached_block.invalidate(); } } @@ -323,7 +324,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let parent_hir_id = tcx.hir.definitions().node_to_hir_id( self.source_scope_local_data[source_scope].lint_root - ); + ); let current_hir_id = tcx.hir.definitions().node_to_hir_id(node_id); sets.lint_level_set(parent_hir_id) == @@ -333,7 +334,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if !same_lint_scopes { self.source_scope = self.new_source_scope(region_scope.1.span, lint_level, - None); + None); } } self.push_scope(region_scope); @@ -381,14 +382,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let scope = self.scopes.pop().unwrap(); assert_eq!(scope.region_scope, region_scope.0); - let resume_block = self.resume_block(); - unpack!(block = build_scope_drops(&mut self.cfg, - resume_block, - &scope, - &self.scopes, - block, - self.arg_count, - false)); + let unwind_to = self.scopes.last().and_then(|next_scope| { + next_scope.cached_unwind.get(false) + }).unwrap_or_else(|| self.resume_block()); + + unpack!(block = build_scope_drops( + &mut self.cfg, + &scope, + block, + unwind_to, + self.arg_count, + false, + )); block.unit() } @@ -396,8 +401,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Branch out of `block` to `target`, exiting all scopes up to /// and including `region_scope`. This will insert whatever drops are - /// needed, as well as tracking this exit for the SEME region. See - /// module comment for details. + /// needed. See module comment for details. pub fn exit_scope(&mut self, span: Span, region_scope: (region::Scope, SourceInfo), @@ -415,38 +419,51 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // If we are emitting a `drop` statement, we need to have the cached // diverge cleanup pads ready in case that drop panics. - let may_panic = self.scopes[(len - scope_count)..].iter() - .any(|s| s.drops.iter().any(|s| s.kind.may_panic())); + let may_panic = self.scopes[(len - scope_count)..].iter().any(|s| s.needs_cleanup); if may_panic { self.diverge_cleanup(); } - { - let resume_block = self.resume_block(); - let mut rest = &mut self.scopes[(len - scope_count)..]; - while let Some((scope, rest_)) = {rest}.split_last_mut() { - rest = rest_; - block = if let Some(&e) = scope.cached_exits.get(&(target, region_scope.0)) { - self.cfg.terminate(block, scope.source_info(span), - TerminatorKind::Goto { target: e }); - return; - } else { - let b = self.cfg.start_new_block(); - self.cfg.terminate(block, scope.source_info(span), - TerminatorKind::Goto { target: b }); - scope.cached_exits.insert((target, region_scope.0), b); - b + let mut scopes = self.scopes[(len - scope_count - 1)..].iter_mut().rev(); + let mut scope = scopes.next().unwrap(); + for next_scope in scopes { + if scope.drops.is_empty() { + scope = next_scope; + continue; + } + let source_info = scope.source_info(span); + block = match scope.cached_exits.entry((target, region_scope.0)) { + Entry::Occupied(e) => { + self.cfg.terminate(block, source_info, + TerminatorKind::Goto { target: *e.get() }); + return; + } + Entry::Vacant(v) => { + let b = self.cfg.start_new_block(); + self.cfg.terminate(block, source_info, + TerminatorKind::Goto { target: b }); + v.insert(b); + b + } }; - unpack!(block = build_scope_drops(&mut self.cfg, - resume_block, - scope, - rest, - block, - self.arg_count, - false)); - } + let unwind_to = next_scope.cached_unwind.get(false).unwrap_or_else(|| { + debug_assert!(!may_panic, "cached block not present?"); + START_BLOCK + }); + + unpack!(block = build_scope_drops( + &mut self.cfg, + scope, + block, + unwind_to, + self.arg_count, + false, + )); + + scope = next_scope; } + let scope = &self.scopes[len - scope_count]; self.cfg.terminate(block, scope.source_info(span), TerminatorKind::Goto { target }); @@ -461,20 +478,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { return None; } - // Fill in the cache + // Fill in the cache for unwinds self.diverge_cleanup_gen(true); let src_info = self.scopes[0].source_info(self.fn_span); + let resume_block = self.resume_block(); + let mut scopes = self.scopes.iter_mut().rev().peekable(); let mut block = self.cfg.start_new_block(); let result = block; - let resume_block = self.resume_block(); - let mut rest = &mut self.scopes[..]; - while let Some((scope, rest_)) = {rest}.split_last_mut() { - rest = rest_; + while let Some(scope) = scopes.next() { if !scope.needs_cleanup { continue; } + block = if let Some(b) = scope.cached_generator_drop { self.cfg.terminate(block, src_info, TerminatorKind::Goto { target: b }); @@ -487,13 +504,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { b }; - unpack!(block = build_scope_drops(&mut self.cfg, - resume_block, - scope, - rest, - block, - self.arg_count, - true)); + let unwind_to = scopes.peek().as_ref().map(|scope| { + scope.cached_unwind.get(true).unwrap_or_else(|| { + span_bug!(src_info.span, "cached block not present?") + }) + }).unwrap_or(resume_block); + + unpack!(block = build_scope_drops( + &mut self.cfg, + scope, + block, + unwind_to, + self.arg_count, + true, + )); } self.cfg.terminate(block, src_info, TerminatorKind::GeneratorDrop); @@ -503,9 +527,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Creates a new source scope, nested in the current one. pub fn new_source_scope(&mut self, - span: Span, - lint_level: LintLevel, - safety: Option) -> SourceScope { + span: Span, + lint_level: LintLevel, + safety: Option) -> SourceScope { let parent = self.source_scope; debug!("new_source_scope({:?}, {:?}, {:?}) - parent({:?})={:?}", span, lint_level, safety, @@ -742,8 +766,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Creates a path that performs all required cleanup for unwinding. /// /// This path terminates in Resume. Returns the start of the path. - /// See module comment for more details. None indicates there’s no - /// cleanup to do at this point. + /// See module comment for more details. pub fn diverge_cleanup(&mut self) -> BasicBlock { self.diverge_cleanup_gen(false) } @@ -765,11 +788,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } fn diverge_cleanup_gen(&mut self, generator_drop: bool) -> BasicBlock { - // To start, create the resume terminator. - let mut target = self.resume_block(); - - let Builder { ref mut cfg, ref mut scopes, .. } = *self; - // Build up the drops in **reverse** order. The end result will // look like: // @@ -781,11 +799,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // store caches. If everything is cached, we'll just walk right // to left reading the cached results but never created anything. - if scopes.iter().any(|scope| scope.needs_cleanup) { - for scope in scopes.iter_mut() { - target = build_diverge_scope(cfg, scope.region_scope_span, - scope, target, generator_drop); - } + // Find the last cached block + let (mut target, first_uncached) = if let Some(cached_index) = self.scopes.iter() + .rposition(|scope| scope.cached_unwind.get(generator_drop).is_some()) { + (self.scopes[cached_index].cached_unwind.get(generator_drop).unwrap(), cached_index + 1) + } else { + (self.resume_block(), 0) + }; + + for scope in self.scopes[first_uncached..].iter_mut() { + target = build_diverge_scope(&mut self.cfg, scope.region_scope_span, + scope, target, generator_drop); } target @@ -859,64 +883,62 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } /// Builds drops for pop_scope and exit_scope. -fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>, - resume_block: BasicBlock, - scope: &Scope<'tcx>, - earlier_scopes: &[Scope<'tcx>], - mut block: BasicBlock, - arg_count: usize, - generator_drop: bool) - -> BlockAnd<()> { - debug!("build_scope_drops({:?} -> {:?})", block, scope); - let mut iter = scope.drops.iter().rev(); - while let Some(drop_data) = iter.next() { +fn build_scope_drops<'tcx>( + cfg: &mut CFG<'tcx>, + scope: &Scope<'tcx>, + mut block: BasicBlock, + last_unwind_to: BasicBlock, + arg_count: usize, + generator_drop: bool, +) -> BlockAnd<()> { + debug!("build_scope_drops({:?} -> {:?}", block, scope); + + // Build up the drops in evaluation order. The end result will + // look like: + // + // [SDs, drops[n]] --..> [SDs, drop[1]] -> [SDs, drop[0]] -> [[SDs]] + // | | | + // : | | + // V V + // [drop[n]] -...-> [drop[1]] ------> [drop[0]] ------> [last_unwind_to] + // + // The horizontal arrows represent the execution path when the drops return + // successfully. The downwards arrows represent the execution path when the + // drops panic (panicking while unwinding will abort, so there's no need for + // another set of arrows). The drops for the unwind path should have already + // been generated by `diverge_cleanup_gen`. + // + // The code in this function reads from right to left. + // Storage dead drops have to be done left to right (since we can only push + // to the end of a Vec). So, we find the next drop and then call + // push_storage_deads which will iterate backwards through them so that + // they are added in the correct order. + + let mut unwind_blocks = scope.drops.iter().rev().filter_map(|drop_data| { + if let DropKind::Value { cached_block } = drop_data.kind { + Some(cached_block.get(generator_drop).unwrap_or_else(|| { + span_bug!(drop_data.span, "cached block not present?") + })) + } else { + None + } + }); + + // When we unwind from a drop, we start cleaning up from the next one, so + // we don't need this block. + unwind_blocks.next(); + + for drop_data in scope.drops.iter().rev() { let source_info = scope.source_info(drop_data.span); match drop_data.kind { DropKind::Value { .. } => { - // Try to find the next block with its cached block for us to - // diverge into, either a previous block in this current scope or - // the top of the previous scope. - // - // If it wasn't for EndRegion, we could just chain all the DropData - // together and pick the first DropKind::Value. Please do that - // when we replace EndRegion with NLL. - let on_diverge = iter.clone().filter_map(|dd| { - match dd.kind { - DropKind::Value { cached_block } => Some(cached_block), - DropKind::Storage => None - } - }).next().or_else(|| { - if earlier_scopes.iter().any(|scope| scope.needs_cleanup) { - // If *any* scope requires cleanup code to be run, - // we must use the cached unwind from the *topmost* - // scope, to ensure all EndRegions from surrounding - // scopes are executed before the drop code runs. - Some(earlier_scopes.last().unwrap().cached_unwind) - } else { - // We don't need any further cleanup, so return None - // to avoid creating a landing pad. We can skip - // EndRegions because all local regions end anyway - // when the function unwinds. - // - // This is an important optimization because LLVM is - // terrible at optimizing landing pads. FIXME: I think - // it would be cleaner and better to do this optimization - // in SimplifyCfg instead of here. - None - } - }); - - let on_diverge = on_diverge.map(|cached_block| { - cached_block.get(generator_drop).unwrap_or_else(|| { - span_bug!(drop_data.span, "cached block not present?") - }) - }); + let unwind_to = unwind_blocks.next().unwrap_or(last_unwind_to); let next = cfg.start_new_block(); cfg.terminate(block, source_info, TerminatorKind::Drop { location: drop_data.location.clone(), target: next, - unwind: Some(on_diverge.unwrap_or(resume_block)) + unwind: Some(unwind_to) }); block = next; } @@ -943,20 +965,17 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>, block.unit() } -fn build_diverge_scope<'a, 'gcx, 'tcx>(cfg: &mut CFG<'tcx>, - span: Span, - scope: &mut Scope<'tcx>, - mut target: BasicBlock, - generator_drop: bool) - -> BasicBlock +fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>, + span: Span, + scope: &mut Scope<'tcx>, + mut target: BasicBlock, + generator_drop: bool) + -> BasicBlock { // Build up the drops in **reverse** order. The end result will // look like: // - // [EndRegion Block] -> [drops[n]] -...-> [drops[0]] -> [Free] -> [target] - // | | - // +---------------------------------------------------------+ - // code for scope + // [drops[n]] -...-> [drops[0]] -> [target] // // The code in this function reads from right to left. At each // point, we check for cached blocks representing the @@ -1001,20 +1020,7 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(cfg: &mut CFG<'tcx>, }; } - // Finally, push the EndRegion block, used by mir-borrowck, and set - // `cached_unwind` to point to it (Block becomes trivial goto after - // pass that removes all EndRegions). - target = { - let cached_block = scope.cached_unwind.ref_mut(generator_drop); - if let Some(cached_block) = *cached_block { - cached_block - } else { - let block = cfg.start_new_cleanup_block(); - cfg.terminate(block, source_info(span), TerminatorKind::Goto { target }); - *cached_block = Some(block); - block - } - }; + *scope.cached_unwind.ref_mut(generator_drop) = Some(target); debug!("build_diverge_scope({:?}, {:?}) = {:?}", scope, span, target); diff --git a/src/test/mir-opt/issue-49232.rs b/src/test/mir-opt/issue-49232.rs index f9024b67063..d8365c8c9cc 100644 --- a/src/test/mir-opt/issue-49232.rs +++ b/src/test/mir-opt/issue-49232.rs @@ -44,7 +44,7 @@ fn main() { // falseUnwind -> [real: bb3, cleanup: bb4]; // } // bb2: { -// goto -> bb29; +// goto -> bb20; // } // bb3: { // StorageLive(_2); @@ -90,58 +90,31 @@ fn main() { // StorageDead(_3); // StorageLive(_6); // _6 = &_2; -// _5 = const std::mem::drop(move _6) -> [return: bb28, unwind: bb4]; +// _5 = const std::mem::drop(move _6) -> [return: bb19, unwind: bb4]; // } // bb15: { +// StorageDead(_3); // goto -> bb16; // } // bb16: { -// goto -> bb17; -// } -// bb17: { -// goto -> bb18; -// } -// bb18: { -// goto -> bb19; -// } -// bb19: { -// goto -> bb20; -// } -// bb20: { -// StorageDead(_3); -// goto -> bb21; -// } -// bb21: { -// goto -> bb22; -// } -// bb22: { // StorageDead(_2); -// goto -> bb23; -// } -// bb23: { -// goto -> bb24; -// } -// bb24: { -// goto -> bb25; -// } -// bb25: { // goto -> bb2; // } -// bb26: { +// bb17: { // _4 = (); // unreachable; // } -// bb27: { +// bb18: { // StorageDead(_4); // goto -> bb14; // } -// bb28: { +// bb19: { // StorageDead(_6); // _1 = (); // StorageDead(_2); // goto -> bb1; // } -// bb29: { +// bb20: { // return; // } // } From 7c9bcc52668a8865f5ed71f1bc3dcead1367e148 Mon Sep 17 00:00:00 2001 From: 0xrgb <0xrgb@users.noreply.github.com> Date: Mon, 19 Nov 2018 15:59:21 +0900 Subject: [PATCH 0054/1984] Update any.rs documentation using keyword dyn --- src/libcore/any.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 6b26093439e..c2113dfd2a0 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -39,7 +39,7 @@ //! //! // Logger function for any type that implements Debug. //! fn log(value: &T) { -//! let value_any = value as &Any; +//! let value_any = value as &dyn Any; //! //! // try to convert our value to a String. If successful, we want to //! // output the String's length as well as its value. If not, it's a @@ -95,7 +95,7 @@ pub trait Any: 'static { /// /// use std::any::{Any, TypeId}; /// - /// fn is_string(s: &Any) -> bool { + /// fn is_string(s: &dyn Any) -> bool { /// TypeId::of::() == s.get_type_id() /// } /// @@ -151,7 +151,7 @@ impl dyn Any { /// ``` /// use std::any::Any; /// - /// fn is_string(s: &Any) { + /// fn is_string(s: &dyn Any) { /// if s.is::() { /// println!("It's a string!"); /// } else { @@ -185,7 +185,7 @@ impl dyn Any { /// ``` /// use std::any::Any; /// - /// fn print_if_string(s: &Any) { + /// fn print_if_string(s: &dyn Any) { /// if let Some(string) = s.downcast_ref::() { /// println!("It's a string({}): '{}'", string.len(), string); /// } else { @@ -218,7 +218,7 @@ impl dyn Any { /// ``` /// use std::any::Any; /// - /// fn modify_if_u32(s: &mut Any) { + /// fn modify_if_u32(s: &mut dyn Any) { /// if let Some(num) = s.downcast_mut::() { /// *num = 42; /// } @@ -256,7 +256,7 @@ impl dyn Any+Send { /// ``` /// use std::any::Any; /// - /// fn is_string(s: &(Any + Send)) { + /// fn is_string(s: &(dyn Any + Send)) { /// if s.is::() { /// println!("It's a string!"); /// } else { @@ -282,7 +282,7 @@ impl dyn Any+Send { /// ``` /// use std::any::Any; /// - /// fn print_if_string(s: &(Any + Send)) { + /// fn print_if_string(s: &(dyn Any + Send)) { /// if let Some(string) = s.downcast_ref::() { /// println!("It's a string({}): '{}'", string.len(), string); /// } else { @@ -308,7 +308,7 @@ impl dyn Any+Send { /// ``` /// use std::any::Any; /// - /// fn modify_if_u32(s: &mut (Any + Send)) { + /// fn modify_if_u32(s: &mut (dyn Any + Send)) { /// if let Some(num) = s.downcast_mut::() { /// *num = 42; /// } @@ -340,7 +340,7 @@ impl dyn Any+Send+Sync { /// ``` /// use std::any::Any; /// - /// fn is_string(s: &(Any + Send + Sync)) { + /// fn is_string(s: &(dyn Any + Send + Sync)) { /// if s.is::() { /// println!("It's a string!"); /// } else { @@ -366,7 +366,7 @@ impl dyn Any+Send+Sync { /// ``` /// use std::any::Any; /// - /// fn print_if_string(s: &(Any + Send + Sync)) { + /// fn print_if_string(s: &(dyn Any + Send + Sync)) { /// if let Some(string) = s.downcast_ref::() { /// println!("It's a string({}): '{}'", string.len(), string); /// } else { @@ -392,7 +392,7 @@ impl dyn Any+Send+Sync { /// ``` /// use std::any::Any; /// - /// fn modify_if_u32(s: &mut (Any + Send + Sync)) { + /// fn modify_if_u32(s: &mut (dyn Any + Send + Sync)) { /// if let Some(num) = s.downcast_mut::() { /// *num = 42; /// } From 8ee9711a6c00a0994f7fc69586273c86ab45e396 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 19 Nov 2018 10:40:09 +0100 Subject: [PATCH 0055/1984] Replace the ICEing on const fn loops with an error --- src/librustc_mir/transform/qualify_min_const_fn.rs | 8 +++----- src/test/ui/consts/min_const_fn/loop_ice.rs | 5 +++++ src/test/ui/consts/min_const_fn/loop_ice.stderr | 8 ++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/consts/min_const_fn/loop_ice.rs create mode 100644 src/test/ui/consts/min_const_fn/loop_ice.stderr diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index ed13063cfdf..958e5efe3ec 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -365,10 +365,8 @@ fn check_terminator( cleanup: _, } => check_operand(tcx, mir, cond, span), - | TerminatorKind::FalseUnwind { .. } => span_bug!( - terminator.source_info.span, - "min_const_fn encountered `{:#?}`", - terminator - ), + TerminatorKind::FalseUnwind { .. } => { + Err((span, "loops are not allowed in const fn".into())) + }, } } diff --git a/src/test/ui/consts/min_const_fn/loop_ice.rs b/src/test/ui/consts/min_const_fn/loop_ice.rs new file mode 100644 index 00000000000..4278a8e2d00 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/loop_ice.rs @@ -0,0 +1,5 @@ +const fn foo() { + loop {} //~ ERROR loops are not allowed in const fn +} + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/loop_ice.stderr b/src/test/ui/consts/min_const_fn/loop_ice.stderr new file mode 100644 index 00000000000..1424cea65af --- /dev/null +++ b/src/test/ui/consts/min_const_fn/loop_ice.stderr @@ -0,0 +1,8 @@ +error: loops are not allowed in const fn + --> $DIR/loop_ice.rs:2:5 + | +LL | loop {} //~ ERROR loops are not allowed in const fn + | ^^^^^^^ + +error: aborting due to previous error + From bc543d7e6c4c87f99eea4dc6217eee54cd7f18b1 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 19 Nov 2018 11:19:14 +0100 Subject: [PATCH 0056/1984] Allow assignments in const contexts --- src/librustc_mir/transform/qualify_consts.rs | 34 ++++++++++++++---- .../assign-to-static-within-other-static.rs | 35 +++++++++++++++++++ ...ssign-to-static-within-other-static.stderr | 8 +++++ .../const-eval/mod-static-with-const-fn.rs | 5 +-- .../mod-static-with-const-fn.stderr | 15 ++------ src/test/ui/consts/const_let_assign.rs | 12 +++++++ src/test/ui/consts/const_let_assign2.rs | 25 +++++++++++++ src/test/ui/consts/const_let_assign3.rs | 22 ++++++++++++ src/test/ui/consts/const_let_assign3.stderr | 9 +++++ 9 files changed, 143 insertions(+), 22 deletions(-) create mode 100644 src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs create mode 100644 src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr create mode 100644 src/test/ui/consts/const_let_assign.rs create mode 100644 src/test/ui/consts/const_let_assign2.rs create mode 100644 src/test/ui/consts/const_let_assign3.rs create mode 100644 src/test/ui/consts/const_let_assign3.stderr diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 00309b0a3e9..31a0dc1494c 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -243,13 +243,29 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { return; } + if self.tcx.features().const_let { + let mut dest = dest; + let index = loop { + match dest { + Place::Local(index) => break *index, + Place::Projection(proj) => dest = &proj.base, + Place::Promoted(..) | Place::Static(..) => { + // Catch more errors in the destination. + self.visit_place( + dest, + PlaceContext::MutatingUse(MutatingUseContext::Store), + location + ); + return; + } + } + }; + debug!("store to var {:?}", index); + self.local_qualif[index] = Some(self.qualif); + return; + } + match *dest { - Place::Local(index) if (self.mir.local_kind(index) == LocalKind::Var || - self.mir.local_kind(index) == LocalKind::Arg) && - self.tcx.sess.features_untracked().const_let => { - debug!("store to var {:?}", index); - self.local_qualif[index] = Some(self.qualif); - } Place::Local(index) if self.mir.local_kind(index) == LocalKind::Temp || self.mir.local_kind(index) == LocalKind::ReturnPointer => { debug!("store to {:?} (temp or return pointer)", index); @@ -478,6 +494,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // Only allow statics (not consts) to refer to other statics. if self.mode == Mode::Static || self.mode == Mode::StaticMut { + if context.is_mutating_use() { + self.tcx.sess.span_err( + self.span, + "cannot mutate statics in the initializer of another static", + ); + } return; } self.add(Qualif::NOT_CONST); diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs new file mode 100644 index 00000000000..5113d73b384 --- /dev/null +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs @@ -0,0 +1,35 @@ +// Copyright 2018 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. + +// New test for #53818: modifying static memory at compile-time is not allowed. +// The test should never compile successfully + +#![feature(const_raw_ptr_deref)] +#![feature(const_let)] + +use std::cell::UnsafeCell; + +struct Foo(UnsafeCell); + +unsafe impl Send for Foo {} +unsafe impl Sync for Foo {} + +static FOO: Foo = Foo(UnsafeCell::new(42)); + +static BAR: () = unsafe { + *FOO.0.get() = 5; +}; + +static mut FOO2: u32 = 42; +static BOO2: () = unsafe { + FOO2 = 5; +}; + +fn main() {} diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr new file mode 100644 index 00000000000..87f02e8e4cf --- /dev/null +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr @@ -0,0 +1,8 @@ +error: cannot mutate statics in the initializer of another static + --> $DIR/assign-to-static-within-other-static.rs:32:5 + | +LL | FOO2 = 5; + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs index 4136a7b6a72..600931e49a0 100644 --- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs +++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs @@ -9,7 +9,7 @@ // except according to those terms. // New test for #53818: modifying static memory at compile-time is not allowed. -// The test should never succeed. +// The test should never compile successfully #![feature(const_raw_ptr_deref)] #![feature(const_let)] @@ -27,9 +27,6 @@ fn foo() {} static BAR: () = unsafe { *FOO.0.get() = 5; - //~^ ERROR statements in statics are unstable (see issue #48821) - // This error is caused by a separate bug that the feature gate error is reported - // even though the feature gate "const_let" is active. foo(); //~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr index c2bba27e4d1..899fc24f153 100644 --- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr +++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr @@ -1,18 +1,9 @@ -error[E0658]: statements in statics are unstable (see issue #48821) - --> $DIR/mod-static-with-const-fn.rs:29:5 - | -LL | *FOO.0.get() = 5; - | ^^^^^^^^^^^^^^^^ - | - = help: add #![feature(const_let)] to the crate attributes to enable - error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants - --> $DIR/mod-static-with-const-fn.rs:34:5 + --> $DIR/mod-static-with-const-fn.rs:31:5 | LL | foo(); | ^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/consts/const_let_assign.rs b/src/test/ui/consts/const_let_assign.rs new file mode 100644 index 00000000000..a3c53a451e1 --- /dev/null +++ b/src/test/ui/consts/const_let_assign.rs @@ -0,0 +1,12 @@ +// compile-pass + +#![feature(const_let)] + +struct S(i32); + +const A: () = { + let mut s = S(0); + s.0 = 1; +}; + +fn main() {} diff --git a/src/test/ui/consts/const_let_assign2.rs b/src/test/ui/consts/const_let_assign2.rs new file mode 100644 index 00000000000..0de7396501a --- /dev/null +++ b/src/test/ui/consts/const_let_assign2.rs @@ -0,0 +1,25 @@ +// compile-pass + +#![feature(const_let)] +#![feature(const_fn)] + +pub struct AA { + pub data: [u8; 10], +} + +impl AA { + pub const fn new() -> Self { + let mut res: AA = AA { data: [0; 10] }; + res.data[0] = 5; + res + } +} + +static mut BB: AA = AA::new(); + +fn main() { + let ptr = unsafe { &mut BB }; + for a in ptr.data.iter() { + println!("{}", a); + } +} diff --git a/src/test/ui/consts/const_let_assign3.rs b/src/test/ui/consts/const_let_assign3.rs new file mode 100644 index 00000000000..83825456b5c --- /dev/null +++ b/src/test/ui/consts/const_let_assign3.rs @@ -0,0 +1,22 @@ +#![feature(const_let)] +#![feature(const_fn)] + +struct S { + state: u32, +} + +impl S { + const fn foo(&mut self, x: u32) { + self.state = x; + } +} + +const FOO: S = { + let mut s = S { state: 42 }; + s.foo(3); //~ ERROR references in constants may only refer to immutable values + s +}; + +fn main() { + assert_eq!(FOO.state, 3); +} diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr new file mode 100644 index 00000000000..7f9a953c10f --- /dev/null +++ b/src/test/ui/consts/const_let_assign3.stderr @@ -0,0 +1,9 @@ +error[E0017]: references in constants may only refer to immutable values + --> $DIR/const_let_assign3.rs:16:5 + | +LL | s.foo(3); //~ ERROR references in constants may only refer to immutable values + | ^ constants require immutable values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0017`. From 30178b422a7a16dc4d48a5ccf7697dba9b79b284 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 7 Nov 2018 12:04:40 -0700 Subject: [PATCH 0057/1984] Disable some pretty-printers when gdb is rust-enabled A rust-enabled gdb already knows how to display string slices, structs, tuples, and enums (and after #54004, the pretty-printers can't handle enums at all). This patch disables these pretty-printers when gdb is rust-enabled. The "gdb-pretty-struct-and-enums-pre-gdb-7-7.rs" test is renamed, because it does not seem to depend on any behavior of that version of gdb, and because gdb 7.7 is 4 years old now. --- src/etc/gdb_rust_pretty_printing.py | 43 +++++++++++-------- ...-7-7.rs => gdb-pretty-struct-and-enums.rs} | 18 ++++---- 2 files changed, 34 insertions(+), 27 deletions(-) rename src/test/debuginfo/{gdb-pretty-struct-and-enums-pre-gdb-7-7.rs => gdb-pretty-struct-and-enums.rs} (72%) diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index e6d5ef1a23f..a5c8e73f919 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -18,6 +18,8 @@ if sys.version_info[0] >= 3: xrange = range +rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string = True) + #=============================================================================== # GDB Pretty Printing Module for Rust #=============================================================================== @@ -99,27 +101,9 @@ def rust_pretty_printer_lookup_function(gdb_val): val = GdbValue(gdb_val) type_kind = val.type.get_type_kind() - if type_kind == rustpp.TYPE_KIND_EMPTY: - return RustEmptyPrinter(val) - - if type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT: - return RustStructPrinter(val, - omit_first_field = False, - omit_type_name = False, - is_tuple_like = False) - - if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT: - return RustStructPrinter(val, - omit_first_field = True, - omit_type_name = False, - is_tuple_like = False) - if type_kind == rustpp.TYPE_KIND_SLICE: return RustSlicePrinter(val) - if type_kind == rustpp.TYPE_KIND_STR_SLICE: - return RustStringSlicePrinter(val) - if type_kind == rustpp.TYPE_KIND_STD_VEC: return RustStdVecPrinter(val) @@ -138,6 +122,29 @@ def rust_pretty_printer_lookup_function(gdb_val): if type_kind == rustpp.TYPE_KIND_OS_STRING: return RustOsStringPrinter(val) + # Checks after this point should only be for "compiler" types -- + # things that gdb's Rust language support knows about. + if rust_enabled: + return None + + if type_kind == rustpp.TYPE_KIND_EMPTY: + return RustEmptyPrinter(val) + + if type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT: + return RustStructPrinter(val, + omit_first_field = False, + omit_type_name = False, + is_tuple_like = False) + + if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT: + return RustStructPrinter(val, + omit_first_field = True, + omit_type_name = False, + is_tuple_like = False) + + if type_kind == rustpp.TYPE_KIND_STR_SLICE: + return RustStringSlicePrinter(val) + if type_kind == rustpp.TYPE_KIND_TUPLE: return RustStructPrinter(val, omit_first_field = False, 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.rs similarity index 72% rename from src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs rename to src/test/debuginfo/gdb-pretty-struct-and-enums.rs index 158a1f17fc0..34fa3bc4b0c 100644 --- a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs +++ b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs @@ -8,34 +8,34 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-bitrig -// ignore-solaris -// ignore-windows failing on win32 bot -// ignore-freebsd: gdb package too new // ignore-tidy-linelength // ignore-lldb // ignore-android: FIXME(#10381) +// min-gdb-version: 7.11 + // compile-flags:-g // gdb-command: run // gdb-command: print regular_struct -// gdb-check:$1 = RegularStruct = {the_first_field = 101, the_second_field = 102.5, the_third_field = false} +// gdbg-check:$1 = RegularStruct = {the_first_field = 101, the_second_field = 102.5, the_third_field = false} +// gdbr-check:$1 = gdb_pretty_struct_and_enums::RegularStruct {the_first_field: 101, the_second_field: 102.5, the_third_field: false} // gdb-command: print empty_struct -// gdb-check:$2 = EmptyStruct +// gdbg-check:$2 = EmptyStruct +// gdbr-check:$2 = gdb_pretty_struct_and_enums::EmptyStruct // gdb-command: print c_style_enum1 // gdbg-check:$3 = CStyleEnumVar1 -// gdbr-check:$3 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar1 +// gdbr-check:$3 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar1 // gdb-command: print c_style_enum2 // gdbg-check:$4 = CStyleEnumVar2 -// gdbr-check:$4 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar2 +// gdbr-check:$4 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar2 // gdb-command: print c_style_enum3 // gdbg-check:$5 = CStyleEnumVar3 -// gdbr-check:$5 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar3 +// gdbr-check:$5 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar3 #![allow(dead_code, unused_variables)] From 59eff14120a067d04832142c8198f0132db2acb0 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 19 Nov 2018 13:49:07 +0100 Subject: [PATCH 0058/1984] Also catch static mutation at evaluation time --- src/librustc/ich/impls_ty.rs | 1 + src/librustc/mir/interpret/error.rs | 3 ++ src/librustc_mir/interpret/memory.rs | 8 ++--- src/librustc_mir/transform/const_prop.rs | 1 + src/librustc_mir/transform/qualify_consts.rs | 7 ++++- .../assign-to-static-within-other-static-2.rs | 30 +++++++++++++++++++ ...ign-to-static-within-other-static-2.stderr | 9 ++++++ .../assign-to-static-within-other-static.rs | 17 ++--------- ...ssign-to-static-within-other-static.stderr | 6 ++-- src/test/ui/error-codes/E0017.rs | 1 + src/test/ui/error-codes/E0017.stderr | 10 +++++-- src/test/ui/error-codes/E0388.rs | 1 + src/test/ui/error-codes/E0388.stderr | 10 +++++-- src/test/ui/write-to-static-mut-in-static.rs | 4 +-- .../ui/write-to-static-mut-in-static.stderr | 9 ++---- 15 files changed, 82 insertions(+), 35 deletions(-) create mode 100644 src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs create mode 100644 src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index f3a62975dd9..fc970400f6c 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -423,6 +423,7 @@ impl_stable_hash_for!( CalledClosureAsFunction, VtableForArgumentlessMethod, ModifiedConstantMemory, + ModifiedStatic, AssumptionNotHeld, InlineAsm, ReallocateNonBasePtr, diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index f28aa41ed42..5895b6cab9a 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -276,6 +276,7 @@ pub enum EvalErrorKind<'tcx, O> { CalledClosureAsFunction, VtableForArgumentlessMethod, ModifiedConstantMemory, + ModifiedStatic, AssumptionNotHeld, InlineAsm, TypeNotPrimitive(Ty<'tcx>), @@ -380,6 +381,8 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> { "tried to call a vtable function without arguments", ModifiedConstantMemory => "tried to modify constant memory", + ModifiedStatic => + "tried to modify a static's initial value from another static's initializer", AssumptionNotHeld => "`assume` argument was false", InlineAsm => diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index e125927e7d2..68a91b0a3bd 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -423,10 +423,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { if alloc.mutability == Mutability::Immutable { return err!(ModifiedConstantMemory); } - let kind = M::STATIC_KIND.expect( - "An allocation is being mutated but the machine does not expect that to happen" - ); - Ok((MemoryKind::Machine(kind), alloc.into_owned())) + match M::STATIC_KIND { + Some(kind) => Ok((MemoryKind::Machine(kind), alloc.into_owned())), + None => err!(ModifiedStatic), + } }); // Unpack the error type manually because type inference doesn't // work otherwise (and we cannot help it because `impl Trait`) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 885d70dc430..51327464266 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -197,6 +197,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { | CalledClosureAsFunction | VtableForArgumentlessMethod | ModifiedConstantMemory + | ModifiedStatic | AssumptionNotHeld // FIXME: should probably be removed and turned into a bug! call | TypeNotPrimitive(_) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 31a0dc1494c..1371b9a9977 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -249,7 +249,8 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { match dest { Place::Local(index) => break *index, Place::Projection(proj) => dest = &proj.base, - Place::Promoted(..) | Place::Static(..) => { + Place::Promoted(..) => bug!("promoteds don't exist yet during promotion"), + Place::Static(..) => { // Catch more errors in the destination. self.visit_place( dest, @@ -495,6 +496,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // Only allow statics (not consts) to refer to other statics. if self.mode == Mode::Static || self.mode == Mode::StaticMut { if context.is_mutating_use() { + // this is not strictly necessary as miri will also bail out + // For interior mutability we can't really catch this statically as that + // goes through raw pointers and intermediate temporaries, so miri has + // to catch this anyway self.tcx.sess.span_err( self.span, "cannot mutate statics in the initializer of another static", diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs new file mode 100644 index 00000000000..ef0de61d219 --- /dev/null +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs @@ -0,0 +1,30 @@ +// Copyright 2018 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. + +// New test for #53818: modifying static memory at compile-time is not allowed. +// The test should never compile successfully + +#![feature(const_raw_ptr_deref)] +#![feature(const_let)] + +use std::cell::UnsafeCell; + +struct Foo(UnsafeCell); + +unsafe impl Send for Foo {} +unsafe impl Sync for Foo {} + +static FOO: Foo = Foo(UnsafeCell::new(42)); + +static BAR: () = unsafe { + *FOO.0.get() = 5; //~ ERROR could not evaluate static initializer +}; + +fn main() {} diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr new file mode 100644 index 00000000000..0892b05a69d --- /dev/null +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr @@ -0,0 +1,9 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/assign-to-static-within-other-static-2.rs:27:5 + | +LL | *FOO.0.get() = 5; //~ ERROR could not evaluate static initializer + | ^^^^^^^^^^^^^^^^ tried to modify a static's initial value from another static's initializer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs index 5113d73b384..6f16f644eec 100644 --- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs @@ -16,20 +16,9 @@ use std::cell::UnsafeCell; -struct Foo(UnsafeCell); - -unsafe impl Send for Foo {} -unsafe impl Sync for Foo {} - -static FOO: Foo = Foo(UnsafeCell::new(42)); - -static BAR: () = unsafe { - *FOO.0.get() = 5; -}; - -static mut FOO2: u32 = 42; -static BOO2: () = unsafe { - FOO2 = 5; +static mut FOO: u32 = 42; +static BOO: () = unsafe { + FOO = 5; //~ ERROR cannot mutate statics in the initializer of another static }; fn main() {} diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr index 87f02e8e4cf..ca652c9df32 100644 --- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr +++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr @@ -1,8 +1,8 @@ error: cannot mutate statics in the initializer of another static - --> $DIR/assign-to-static-within-other-static.rs:32:5 + --> $DIR/assign-to-static-within-other-static.rs:21:5 | -LL | FOO2 = 5; - | ^^^^^^^^ +LL | FOO = 5; //~ ERROR cannot mutate statics in the initializer of another static + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0017.rs b/src/test/ui/error-codes/E0017.rs index c98c35a1442..bf400fde365 100644 --- a/src/test/ui/error-codes/E0017.rs +++ b/src/test/ui/error-codes/E0017.rs @@ -14,5 +14,6 @@ const C: i32 = 2; const CR: &'static mut i32 = &mut C; //~ ERROR E0017 static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 //~| ERROR cannot borrow + //~| ERROR cannot mutate statics static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 fn main() {} diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr index 411b9f31397..94a90d92d3e 100644 --- a/src/test/ui/error-codes/E0017.stderr +++ b/src/test/ui/error-codes/E0017.stderr @@ -4,6 +4,12 @@ error[E0017]: references in constants may only refer to immutable values LL | const CR: &'static mut i32 = &mut C; //~ ERROR E0017 | ^^^^^^ constants require immutable values +error: cannot mutate statics in the initializer of another static + --> $DIR/E0017.rs:15:39 + | +LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 + | ^^^^^^ + error[E0017]: references in statics may only refer to immutable values --> $DIR/E0017.rs:15:39 | @@ -17,12 +23,12 @@ LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 | ^ error[E0017]: references in statics may only refer to immutable values - --> $DIR/E0017.rs:17:38 + --> $DIR/E0017.rs:18:38 | LL | static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 | ^^^^^^ statics require immutable values -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors occurred: E0017, E0596. For more information about an error, try `rustc --explain E0017`. diff --git a/src/test/ui/error-codes/E0388.rs b/src/test/ui/error-codes/E0388.rs index c002badfef6..3203798c709 100644 --- a/src/test/ui/error-codes/E0388.rs +++ b/src/test/ui/error-codes/E0388.rs @@ -14,6 +14,7 @@ const C: i32 = 2; const CR: &'static mut i32 = &mut C; //~ ERROR E0017 static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 //~| ERROR cannot borrow + //~| ERROR cannot mutate statics static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 fn main() {} diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr index d2263cd4034..46efda9147b 100644 --- a/src/test/ui/error-codes/E0388.stderr +++ b/src/test/ui/error-codes/E0388.stderr @@ -4,6 +4,12 @@ error[E0017]: references in constants may only refer to immutable values LL | const CR: &'static mut i32 = &mut C; //~ ERROR E0017 | ^^^^^^ constants require immutable values +error: cannot mutate statics in the initializer of another static + --> $DIR/E0388.rs:15:39 + | +LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 + | ^^^^^^ + error[E0017]: references in statics may only refer to immutable values --> $DIR/E0388.rs:15:39 | @@ -17,12 +23,12 @@ LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 | ^ error[E0017]: references in statics may only refer to immutable values - --> $DIR/E0388.rs:17:38 + --> $DIR/E0388.rs:18:38 | LL | static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 | ^^^^^^ statics require immutable values -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors occurred: E0017, E0596. For more information about an error, try `rustc --explain E0017`. diff --git a/src/test/ui/write-to-static-mut-in-static.rs b/src/test/ui/write-to-static-mut-in-static.rs index 1ea74f73723..191f09b54ee 100644 --- a/src/test/ui/write-to-static-mut-in-static.rs +++ b/src/test/ui/write-to-static-mut-in-static.rs @@ -12,10 +12,10 @@ pub static mut A: u32 = 0; pub static mut B: () = unsafe { A = 1; }; -//~^ ERROR statements in statics are unstable +//~^ ERROR cannot mutate statics in the initializer of another static pub static mut C: u32 = unsafe { C = 1; 0 }; -//~^ ERROR statements in statics are unstable +//~^ ERROR cannot mutate statics in the initializer of another static pub static D: u32 = D; diff --git a/src/test/ui/write-to-static-mut-in-static.stderr b/src/test/ui/write-to-static-mut-in-static.stderr index f07d240746f..673a71b4642 100644 --- a/src/test/ui/write-to-static-mut-in-static.stderr +++ b/src/test/ui/write-to-static-mut-in-static.stderr @@ -1,19 +1,14 @@ -error[E0658]: statements in statics are unstable (see issue #48821) +error: cannot mutate statics in the initializer of another static --> $DIR/write-to-static-mut-in-static.rs:14:33 | LL | pub static mut B: () = unsafe { A = 1; }; | ^^^^^ - | - = help: add #![feature(const_let)] to the crate attributes to enable -error[E0658]: statements in statics are unstable (see issue #48821) +error: cannot mutate statics in the initializer of another static --> $DIR/write-to-static-mut-in-static.rs:17:34 | LL | pub static mut C: u32 = unsafe { C = 1; 0 }; | ^^^^^ - | - = help: add #![feature(const_let)] to the crate attributes to enable error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. From a44e446551a7251a06c23caa97aebcfbb98c79b2 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Mon, 19 Nov 2018 15:04:28 +0530 Subject: [PATCH 0059/1984] Add `override_export_symbols` option to Rust target specification --- src/librustc_codegen_ssa/back/linker.rs | 4 ++++ src/librustc_target/spec/mod.rs | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index da9cfbb94d1..ec5ca580104 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -1050,6 +1050,10 @@ impl<'a> Linker for WasmLd<'a> { } fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec { + if let Some(ref exports) = tcx.sess.target.target.options.override_export_symbols { + return exports.clone() + } + let mut symbols = Vec::new(); let export_threshold = symbol_export::crates_export_threshold(&[crate_type]); diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 16dc2a91030..57bbf6b0260 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -683,6 +683,10 @@ pub struct TargetOptions { /// target features. This is `true` by default, and `false` for targets like /// wasm32 where the whole program either has simd or not. pub simd_types_indirect: bool, + + /// If set, have the linker export exactly these symbols, instead of using + /// the usual logic to figure this out from the crate itself. + pub override_export_symbols: Option> } impl Default for TargetOptions { @@ -763,6 +767,7 @@ impl Default for TargetOptions { emit_debug_gdb_scripts: true, requires_uwtable: false, simd_types_indirect: true, + override_export_symbols: None, } } } @@ -898,6 +903,14 @@ impl Target { ) ); } ); + ($key_name:ident, opt_list) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).map(|o| o.as_array() + .map(|v| base.options.$key_name = Some(v.iter() + .map(|a| a.as_string().unwrap().to_string()).collect()) + ) + ); + } ); ($key_name:ident, optional) => ( { let name = (stringify!($key_name)).replace("_", "-"); if let Some(o) = obj.find(&name[..]) { @@ -1044,6 +1057,7 @@ impl Target { key!(emit_debug_gdb_scripts, bool); key!(requires_uwtable, bool); key!(simd_types_indirect, bool); + key!(override_export_symbols, opt_list); if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) { for name in array.iter().filter_map(|abi| abi.as_string()) { @@ -1253,6 +1267,7 @@ impl ToJson for Target { target_option_val!(emit_debug_gdb_scripts); target_option_val!(requires_uwtable); target_option_val!(simd_types_indirect); + target_option_val!(override_export_symbols); if default.abi_blacklist != self.options.abi_blacklist { d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter() From 7d5b5ff24df9aa98e2be212b8bc7887fcc5ac16c Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 19 Nov 2018 19:03:03 +0100 Subject: [PATCH 0060/1984] Update nll stderr files --- src/test/ui/error-codes/E0017.nll.stderr | 10 ++++++++-- src/test/ui/error-codes/E0388.nll.stderr | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/test/ui/error-codes/E0017.nll.stderr b/src/test/ui/error-codes/E0017.nll.stderr index 08708d213d3..8f8d87739b8 100644 --- a/src/test/ui/error-codes/E0017.nll.stderr +++ b/src/test/ui/error-codes/E0017.nll.stderr @@ -4,6 +4,12 @@ error[E0017]: references in constants may only refer to immutable values LL | const CR: &'static mut i32 = &mut C; //~ ERROR E0017 | ^^^^^^ constants require immutable values +error: cannot mutate statics in the initializer of another static + --> $DIR/E0017.rs:15:39 + | +LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 + | ^^^^^^ + error[E0017]: references in statics may only refer to immutable values --> $DIR/E0017.rs:15:39 | @@ -17,12 +23,12 @@ LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 | ^^^^^^ cannot borrow as mutable error[E0017]: references in statics may only refer to immutable values - --> $DIR/E0017.rs:17:38 + --> $DIR/E0017.rs:18:38 | LL | static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 | ^^^^^^ statics require immutable values -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors occurred: E0017, E0596. For more information about an error, try `rustc --explain E0017`. diff --git a/src/test/ui/error-codes/E0388.nll.stderr b/src/test/ui/error-codes/E0388.nll.stderr index a048374a497..7d25d41f18b 100644 --- a/src/test/ui/error-codes/E0388.nll.stderr +++ b/src/test/ui/error-codes/E0388.nll.stderr @@ -4,6 +4,12 @@ error[E0017]: references in constants may only refer to immutable values LL | const CR: &'static mut i32 = &mut C; //~ ERROR E0017 | ^^^^^^ constants require immutable values +error: cannot mutate statics in the initializer of another static + --> $DIR/E0388.rs:15:39 + | +LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 + | ^^^^^^ + error[E0017]: references in statics may only refer to immutable values --> $DIR/E0388.rs:15:39 | @@ -17,12 +23,12 @@ LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017 | ^^^^^^ cannot borrow as mutable error[E0017]: references in statics may only refer to immutable values - --> $DIR/E0388.rs:17:38 + --> $DIR/E0388.rs:18:38 | LL | static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 | ^^^^^^ statics require immutable values -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors occurred: E0017, E0596. For more information about an error, try `rustc --explain E0017`. From 089a50411f3bceb233dd5da8057252ff7b6b47e1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 19 Nov 2018 12:05:21 -0800 Subject: [PATCH 0061/1984] Encode a custom "producers" section in wasm files This commit implements WebAssembly/tool-conventions#65 for wasm files produced by the Rust compiler. This adds a bit of metadata to wasm modules to indicate that the file's language includes Rust and the file's "processed-by" tools includes rustc. The thinking with this section is to eventually have telemetry in browsers tracking all this. --- src/librustc_codegen_llvm/back/link.rs | 5 ++ src/librustc_codegen_llvm/back/wasm.rs | 107 +++++++++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index 20f05d11087..fa9a852ad01 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -692,6 +692,11 @@ fn link_natively(sess: &Session, if sess.opts.target_triple.triple() == "wasm32-unknown-unknown" { wasm::rewrite_imports(&out_filename, &codegen_results.crate_info.wasm_imports); + wasm::add_producer_section( + &out_filename, + &sess.edition().to_string(), + option_env!("CFG_VERSION").unwrap_or("unknown"), + ); } } diff --git a/src/librustc_codegen_llvm/back/wasm.rs b/src/librustc_codegen_llvm/back/wasm.rs index 7101255173c..1a5c65f3c43 100644 --- a/src/librustc_codegen_llvm/back/wasm.rs +++ b/src/librustc_codegen_llvm/back/wasm.rs @@ -17,6 +17,7 @@ use serialize::leb128; // https://webassembly.github.io/spec/core/binary/modules.html#binary-importsec const WASM_IMPORT_SECTION_ID: u8 = 2; +const WASM_CUSTOM_SECTION_ID: u8 = 0; const WASM_EXTERNAL_KIND_FUNCTION: u8 = 0; const WASM_EXTERNAL_KIND_TABLE: u8 = 1; @@ -121,6 +122,112 @@ pub fn rewrite_imports(path: &Path, import_map: &FxHashMap) { } } +/// Add or augment the existing `producers` section to encode information about +/// the Rust compiler used to produce the wasm file. +pub fn add_producer_section( + path: &Path, + rust_version: &str, + rustc_version: &str, +) { + struct Field<'a> { + name: &'a str, + values: Vec>, + } + + #[derive(Copy, Clone)] + struct FieldValue<'a> { + name: &'a str, + version: &'a str, + } + + let wasm = fs::read(path).expect("failed to read wasm output"); + let mut ret = WasmEncoder::new(); + ret.data.extend(&wasm[..8]); + + // skip the 8 byte wasm/version header + let rustc_value = FieldValue { + name: "rustc", + version: rustc_version, + }; + let rust_value = FieldValue { + name: "Rust", + version: rust_version, + }; + let mut fields = Vec::new(); + let mut wrote_rustc = false; + let mut wrote_rust = false; + + // Move all sections from the original wasm file to our output, skipping + // everything except the producers section + for (id, raw) in WasmSections(WasmDecoder::new(&wasm[8..])) { + if id != WASM_CUSTOM_SECTION_ID { + ret.byte(id); + ret.bytes(raw); + continue + } + let mut decoder = WasmDecoder::new(raw); + if decoder.str() != "producers" { + ret.byte(id); + ret.bytes(raw); + continue + } + + // Read off the producers section into our fields outside the loop, + // we'll re-encode the producers section when we're done (to handle an + // entirely missing producers section as well). + info!("rewriting existing producers section"); + + for _ in 0..decoder.u32() { + let name = decoder.str(); + let mut values = Vec::new(); + for _ in 0..decoder.u32() { + let name = decoder.str(); + let version = decoder.str(); + values.push(FieldValue { name, version }); + } + + if name == "language" { + values.push(rust_value); + wrote_rust = true; + } else if name == "processed-by" { + values.push(rustc_value); + wrote_rustc = true; + } + fields.push(Field { name, values }); + } + } + + if !wrote_rust { + fields.push(Field { + name: "language", + values: vec![rust_value], + }); + } + if !wrote_rustc { + fields.push(Field { + name: "processed-by", + values: vec![rustc_value], + }); + } + + // Append the producers section to the end of the wasm file. + let mut section = WasmEncoder::new(); + section.str("producers"); + section.u32(fields.len() as u32); + for field in fields { + section.str(field.name); + section.u32(field.values.len() as u32); + for value in field.values { + section.str(value.name); + section.str(value.version); + } + } + ret.byte(WASM_CUSTOM_SECTION_ID); + ret.bytes(§ion.data); + + fs::write(path, &ret.data).expect("failed to write wasm output"); +} + struct WasmSections<'a>(WasmDecoder<'a>); impl<'a> Iterator for WasmSections<'a> { From b8da7190243faca8dc0a5173496034b772ff4449 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 19 Nov 2018 13:29:35 -0800 Subject: [PATCH 0062/1984] Fix error message for `-C panic=xxx`. --- src/librustc/session/config.rs | 2 +- src/test/ui/panic-runtime/bad-panic-flag1.rs | 2 +- src/test/ui/panic-runtime/bad-panic-flag1.stderr | 2 +- src/test/ui/panic-runtime/bad-panic-flag2.rs | 2 +- src/test/ui/panic-runtime/bad-panic-flag2.stderr | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index ee6d970750a..c620e092f36 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -802,7 +802,7 @@ macro_rules! options { pub const parse_opt_uint: Option<&'static str> = Some("a number"); pub const parse_panic_strategy: Option<&'static str> = - Some("either `panic` or `abort`"); + Some("either `unwind` or `abort`"); pub const parse_relro_level: Option<&'static str> = Some("one of: `full`, `partial`, or `off`"); pub const parse_sanitizer: Option<&'static str> = diff --git a/src/test/ui/panic-runtime/bad-panic-flag1.rs b/src/test/ui/panic-runtime/bad-panic-flag1.rs index f067b6b8349..4e553c4df2f 100644 --- a/src/test/ui/panic-runtime/bad-panic-flag1.rs +++ b/src/test/ui/panic-runtime/bad-panic-flag1.rs @@ -9,6 +9,6 @@ // except according to those terms. // compile-flags:-C panic=foo -// error-pattern:either `panic` or `abort` was expected +// error-pattern:either `unwind` or `abort` was expected fn main() {} diff --git a/src/test/ui/panic-runtime/bad-panic-flag1.stderr b/src/test/ui/panic-runtime/bad-panic-flag1.stderr index 3a65419c98f..013373c6f93 100644 --- a/src/test/ui/panic-runtime/bad-panic-flag1.stderr +++ b/src/test/ui/panic-runtime/bad-panic-flag1.stderr @@ -1,2 +1,2 @@ -error: incorrect value `foo` for codegen option `panic` - either `panic` or `abort` was expected +error: incorrect value `foo` for codegen option `panic` - either `unwind` or `abort` was expected diff --git a/src/test/ui/panic-runtime/bad-panic-flag2.rs b/src/test/ui/panic-runtime/bad-panic-flag2.rs index 0ecf65f080f..f560e7f4eb2 100644 --- a/src/test/ui/panic-runtime/bad-panic-flag2.rs +++ b/src/test/ui/panic-runtime/bad-panic-flag2.rs @@ -9,6 +9,6 @@ // except according to those terms. // compile-flags:-C panic -// error-pattern:requires either `panic` or `abort` +// error-pattern:requires either `unwind` or `abort` fn main() {} diff --git a/src/test/ui/panic-runtime/bad-panic-flag2.stderr b/src/test/ui/panic-runtime/bad-panic-flag2.stderr index 8d919e55c90..6ab94ea704d 100644 --- a/src/test/ui/panic-runtime/bad-panic-flag2.stderr +++ b/src/test/ui/panic-runtime/bad-panic-flag2.stderr @@ -1,2 +1,2 @@ -error: codegen option `panic` requires either `panic` or `abort` (C panic=) +error: codegen option `panic` requires either `unwind` or `abort` (C panic=) From 10a520af5f0561df94ad382bb9da270663fc9498 Mon Sep 17 00:00:00 2001 From: Who? Me?! Date: Mon, 19 Nov 2018 15:45:19 -0600 Subject: [PATCH 0063/1984] Link to rustc guide As proposed in https://github.com/rust-lang-nursery/rustc-guide/issues/239 --- src/doc/index.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/doc/index.md b/src/doc/index.md index 33ee76739c5..f702052e049 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -104,3 +104,9 @@ Rust. It's also sometimes called "the 'nomicon." ## The Unstable Book [The Unstable Book](unstable-book/index.html) has documentation for unstable features. + +## The `rustc` Contribution Guide + +[The `rustc` Guide](https://rust-lang-nursery.github.io/rustc-guide/) documents how +the compiler works and how to contribute to it. This is useful if you want to build +or modify the Rust compiler from source (e.g. to target something non-standard). From 28cc944530420bb3b1fc2dc96e2a8f433a41c6e4 Mon Sep 17 00:00:00 2001 From: Who? Me?! Date: Mon, 19 Nov 2018 15:50:24 -0600 Subject: [PATCH 0064/1984] Reduce the amount of bold text at doc.rust-lang.org --- src/doc/index.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/doc/index.md b/src/doc/index.md index 33ee76739c5..b79a349a453 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -21,6 +21,9 @@ nav { #search-but:hover, #search-input:focus { border-color: #55a9ff; } +h2 { + font-size: 18px; +} Welcome to an overview of the documentation provided by the Rust project. From c7dc868ed7b2899f585fa64ede938e665f965067 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 19 Nov 2018 23:26:00 -0500 Subject: [PATCH 0065/1984] Fix json output in the self-profiler Fix missing ',' array element separators and convert NaN's to 0. --- src/librustc/util/profiling.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/librustc/util/profiling.rs b/src/librustc/util/profiling.rs index 37073b6e820..dfd3f2ee184 100644 --- a/src/librustc/util/profiling.rs +++ b/src/librustc/util/profiling.rs @@ -93,16 +93,27 @@ macro_rules! define_categories { $( let (hits, total) = self.query_counts.$name; + //normalize hits to 0% + let hit_percent = + if total > 0 { + ((hits as f32) / (total as f32)) * 100.0 + } else { + 0.0 + }; + json.push_str(&format!( "{{ \"category\": {}, \"time_ms\": {}, - \"query_count\": {}, \"query_hits\": {} }}", + \"query_count\": {}, \"query_hits\": {} }},", stringify!($name), self.times.$name / 1_000_000, total, - format!("{:.2}", (((hits as f32) / (total as f32)) * 100.0)) + format!("{:.2}", hit_percent) )); )* + //remove the trailing ',' character + json.pop(); + json.push(']'); json From 6674db48872c1b84fe3ac3feb94b8d3e0ee82b24 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 20 Nov 2018 20:16:57 +1100 Subject: [PATCH 0066/1984] Reuse the `P` in `InvocationCollector::fold_{,opt_}expr`. This requires adding a new method, `P::filter_map`. This commit reduces instruction counts for various benchmarks by up to 0.7%. --- src/libsyntax/ext/expand.rs | 84 +++++++++++++++++++++---------------- src/libsyntax/ptr.rs | 28 +++++++++++-- 2 files changed, 73 insertions(+), 39 deletions(-) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index cc8af70a050..68a96293891 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1201,50 +1201,62 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { fn fold_expr(&mut self, expr: P) -> P { - let mut expr = self.cfg.configure_expr(expr).into_inner(); - expr.node = self.cfg.configure_expr_kind(expr.node); - - // ignore derives so they remain unused - let (attr, expr, after_derive) = self.classify_nonitem(expr); - - if attr.is_some() { - // collect the invoc regardless of whether or not attributes are permitted here - // expansion will eat the attribute so it won't error later - attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); - - // AstFragmentKind::Expr requires the macro to emit an expression - return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), - AstFragmentKind::Expr, after_derive).make_expr(); - } + let expr = self.cfg.configure_expr(expr); + expr.map(|mut expr| { + expr.node = self.cfg.configure_expr_kind(expr.node); + + // ignore derives so they remain unused + let (attr, expr, after_derive) = self.classify_nonitem(expr); + + if attr.is_some() { + // Collect the invoc regardless of whether or not attributes are permitted here + // expansion will eat the attribute so it won't error later. + attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); + + // AstFragmentKind::Expr requires the macro to emit an expression. + return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), + AstFragmentKind::Expr, after_derive) + .make_expr() + .into_inner() + } - if let ast::ExprKind::Mac(mac) = expr.node { - self.check_attributes(&expr.attrs); - self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr() - } else { - P(noop_fold_expr(expr, self)) - } + if let ast::ExprKind::Mac(mac) = expr.node { + self.check_attributes(&expr.attrs); + self.collect_bang(mac, expr.span, AstFragmentKind::Expr) + .make_expr() + .into_inner() + } else { + noop_fold_expr(expr, self) + } + }) } fn fold_opt_expr(&mut self, expr: P) -> Option> { - let mut expr = configure!(self, expr).into_inner(); - expr.node = self.cfg.configure_expr_kind(expr.node); + let expr = configure!(self, expr); + expr.filter_map(|mut expr| { + expr.node = self.cfg.configure_expr_kind(expr.node); - // ignore derives so they remain unused - let (attr, expr, after_derive) = self.classify_nonitem(expr); + // Ignore derives so they remain unused. + let (attr, expr, after_derive) = self.classify_nonitem(expr); - if attr.is_some() { - attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); + if attr.is_some() { + attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); - return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), - AstFragmentKind::OptExpr, after_derive).make_opt_expr(); - } + return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), + AstFragmentKind::OptExpr, after_derive) + .make_opt_expr() + .map(|expr| expr.into_inner()) + } - if let ast::ExprKind::Mac(mac) = expr.node { - self.check_attributes(&expr.attrs); - self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr).make_opt_expr() - } else { - Some(P(noop_fold_expr(expr, self))) - } + if let ast::ExprKind::Mac(mac) = expr.node { + self.check_attributes(&expr.attrs); + self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr) + .make_opt_expr() + .map(|expr| expr.into_inner()) + } else { + Some(noop_fold_expr(expr, self)) + } + }) } fn fold_pat(&mut self, pat: P) -> P { diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index bb47d9b535b..9fbc64758da 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -72,7 +72,7 @@ impl P { *self.ptr } - /// Transform the inner value, consuming `self` and producing a new `P`. + /// Produce a new `P` from `self` without reallocating. pub fn map(mut self, f: F) -> P where F: FnOnce(T) -> T, { @@ -88,8 +88,30 @@ impl P { ptr::write(p, f(ptr::read(p))); // Recreate self from the raw pointer. - P { - ptr: Box::from_raw(p) + P { ptr: Box::from_raw(p) } + } + } + + /// Optionally produce a new `P` from `self` without reallocating. + pub fn filter_map(mut self, f: F) -> Option> where + F: FnOnce(T) -> Option, + { + let p: *mut T = &mut *self.ptr; + + // Leak self in case of panic. + // FIXME(eddyb) Use some sort of "free guard" that + // only deallocates, without dropping the pointee, + // in case the call the `f` below ends in a panic. + mem::forget(self); + + unsafe { + if let Some(v) = f(ptr::read(p)) { + ptr::write(p, v); + + // Recreate self from the raw pointer. + Some(P { ptr: Box::from_raw(p) }) + } else { + None } } } From f98235ed9d8be7a6966764384a99e18ead1195e2 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 20 Nov 2018 11:11:09 +0100 Subject: [PATCH 0067/1984] Document runtime static mutation checks --- src/librustc_mir/interpret/machine.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 57640dc48f1..4d8f40c8130 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -89,7 +89,8 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { Default + Clone; - /// The memory kind to use for copied statics -- or None if those are not supported. + /// The memory kind to use for copied statics -- or None if statics should not be mutated + /// and thus any such attempt will cause a `ModifiedStatic` error is raised. /// Statics are copied under two circumstances: When they are mutated, and when /// `static_with_default_tag` or `find_foreign_static` (see below) returns an owned allocation /// that is added to the memory so that the work is not done twice. From 6bcb0d6152e0b817da7af23bdb2abf13a8b2db43 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 20 Nov 2018 11:13:19 +0100 Subject: [PATCH 0068/1984] Explain missing error in test --- src/test/ui/consts/const-eval/mod-static-with-const-fn.rs | 3 +++ src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs index 600931e49a0..01fcc8307c0 100644 --- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs +++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs @@ -27,6 +27,9 @@ fn foo() {} static BAR: () = unsafe { *FOO.0.get() = 5; + // we do not error on the above access, because that is not detectable statically. Instead, + // const evaluation will error when trying to evaluate it. Due to the error below, we never even + // attempt to const evaluate `BAR`, so we don't see the error foo(); //~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr index 899fc24f153..01ad1fc9a21 100644 --- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr +++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr @@ -1,5 +1,5 @@ error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants - --> $DIR/mod-static-with-const-fn.rs:31:5 + --> $DIR/mod-static-with-const-fn.rs:34:5 | LL | foo(); | ^^^^^ From f70abe8d07023bc58cac03a989ddbd37332fa10f Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 20 Nov 2018 11:33:46 +0100 Subject: [PATCH 0069/1984] Add sanity test for promotion and `const_let` --- src/test/ui/consts/promote_const_let.nll.stderr | 14 ++++++++++++++ src/test/ui/consts/promote_const_let.rs | 8 ++++++++ src/test/ui/consts/promote_const_let.stderr | 13 +++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 src/test/ui/consts/promote_const_let.nll.stderr create mode 100644 src/test/ui/consts/promote_const_let.rs create mode 100644 src/test/ui/consts/promote_const_let.stderr diff --git a/src/test/ui/consts/promote_const_let.nll.stderr b/src/test/ui/consts/promote_const_let.nll.stderr new file mode 100644 index 00000000000..d8749bb5fd9 --- /dev/null +++ b/src/test/ui/consts/promote_const_let.nll.stderr @@ -0,0 +1,14 @@ +error[E0597]: `y` does not live long enough + --> $DIR/promote_const_let.rs:6:9 + | +LL | let x: &'static u32 = { + | ------------ type annotation requires that `y` is borrowed for `'static` +LL | let y = 42; +LL | &y //~ ERROR does not live long enough + | ^^ borrowed value does not live long enough +LL | }; + | - `y` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/consts/promote_const_let.rs b/src/test/ui/consts/promote_const_let.rs new file mode 100644 index 00000000000..1ba406a957d --- /dev/null +++ b/src/test/ui/consts/promote_const_let.rs @@ -0,0 +1,8 @@ +#![feature(const_let)] + +fn main() { + let x: &'static u32 = { + let y = 42; + &y //~ ERROR does not live long enough + }; +} \ No newline at end of file diff --git a/src/test/ui/consts/promote_const_let.stderr b/src/test/ui/consts/promote_const_let.stderr new file mode 100644 index 00000000000..6bbb7495fb0 --- /dev/null +++ b/src/test/ui/consts/promote_const_let.stderr @@ -0,0 +1,13 @@ +error[E0597]: `y` does not live long enough + --> $DIR/promote_const_let.rs:6:10 + | +LL | &y //~ ERROR does not live long enough + | ^ borrowed value does not live long enough +LL | }; + | - borrowed value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. From 86d41350c790502d3a1227bab3433ac7472ccb4c Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 20 Nov 2018 12:14:53 +0100 Subject: [PATCH 0070/1984] Fix invalid bitcast taking bool out of a union represented as a scalar As reported in https://github.com/rust-lang/rust/pull/54668#issuecomment-440186476 --- src/librustc_codegen_ssa/mir/operand.rs | 14 +++++++++++--- src/test/codegen/union-abi.rs | 6 ++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index d574d89d67e..859047f5491 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -243,14 +243,22 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> { _ => bug!("OperandRef::extract_field({:?}): not applicable", self) }; + let bitcast = |bx: &mut Bx, val, ty| { + if ty == bx.cx().type_i1() { + bx.trunc(val, ty) + } else { + bx.bitcast(val, ty) + } + }; + // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. match val { OperandValue::Immediate(ref mut llval) => { - *llval = bx.bitcast(*llval, bx.cx().immediate_backend_type(field)); + *llval = bitcast(bx, *llval, bx.cx().immediate_backend_type(field)); } OperandValue::Pair(ref mut a, ref mut b) => { - *a = bx.bitcast(*a, bx.cx().scalar_pair_element_backend_type(field, 0, true)); - *b = bx.bitcast(*b, bx.cx().scalar_pair_element_backend_type(field, 1, true)); + *a = bitcast(bx, *a, bx.cx().scalar_pair_element_backend_type(field, 0, true)); + *b = bitcast(bx, *b, bx.cx().scalar_pair_element_backend_type(field, 1, true)); } OperandValue::Ref(..) => bug!() } diff --git a/src/test/codegen/union-abi.rs b/src/test/codegen/union-abi.rs index 786968128ec..5a6df52502e 100644 --- a/src/test/codegen/union-abi.rs +++ b/src/test/codegen/union-abi.rs @@ -78,3 +78,9 @@ pub union CUnionU128{a:u128} #[no_mangle] pub fn test_CUnionU128(_: CUnionU128) { loop {} } +pub union UnionBool { b:bool } +// CHECK: define zeroext i1 @test_UnionBool(i8 %b) +#[no_mangle] +pub fn test_UnionBool(b: UnionBool) -> bool { unsafe { b.b } } +// CHECK: %0 = trunc i8 %b to i1 + From 7d96f2c4814cdf07860d31e8e8b9695eb9628972 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 20 Nov 2018 12:25:44 +0100 Subject: [PATCH 0071/1984] Document qualify_consts more --- src/librustc_mir/transform/qualify_consts.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 1371b9a9977..f8ecd963457 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -247,11 +247,16 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { let mut dest = dest; let index = loop { match dest { + // with `const_let` active, we treat all locals equal Place::Local(index) => break *index, + // projections are transparent for assignments + // we qualify the entire destination at once, even if just a field would have + // stricter qualification Place::Projection(proj) => dest = &proj.base, Place::Promoted(..) => bug!("promoteds don't exist yet during promotion"), Place::Static(..) => { - // Catch more errors in the destination. + // Catch more errors in the destination. `visit_place` also checks that we + // do not try to access statics from constants or try to mutate statics self.visit_place( dest, PlaceContext::MutatingUse(MutatingUseContext::Store), From 3e081c7e824eab1e5d87462e5e6a46be14c529ea Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 20 Nov 2018 12:28:24 +0100 Subject: [PATCH 0072/1984] Trailing newline --- src/test/ui/consts/promote_const_let.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/consts/promote_const_let.rs b/src/test/ui/consts/promote_const_let.rs index 1ba406a957d..8de9b00eb11 100644 --- a/src/test/ui/consts/promote_const_let.rs +++ b/src/test/ui/consts/promote_const_let.rs @@ -5,4 +5,4 @@ fn main() { let y = 42; &y //~ ERROR does not live long enough }; -} \ No newline at end of file +} From 37fcd5cad5c314632aede576ae5fbbb1c3ede228 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 20 Nov 2018 12:29:05 +0100 Subject: [PATCH 0073/1984] Grammar nit --- src/librustc_mir/interpret/machine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 4d8f40c8130..dd247a96fa4 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -90,7 +90,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { Clone; /// The memory kind to use for copied statics -- or None if statics should not be mutated - /// and thus any such attempt will cause a `ModifiedStatic` error is raised. + /// and thus any such attempt will cause a `ModifiedStatic` error to be raised. /// Statics are copied under two circumstances: When they are mutated, and when /// `static_with_default_tag` or `find_foreign_static` (see below) returns an owned allocation /// that is added to the memory so that the work is not done twice. From 4c21f66c1dffefa0dbeec3e409aa77630cb9a448 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 20 Nov 2018 13:24:41 +0100 Subject: [PATCH 0074/1984] Add comments and rename a local variable --- src/librustc_codegen_ssa/mir/operand.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 859047f5491..a91e9318471 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -243,7 +243,9 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> { _ => bug!("OperandRef::extract_field({:?}): not applicable", self) }; - let bitcast = |bx: &mut Bx, val, ty| { + // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. + // Bools in union fields needs to be truncated. + let to_immediate_or_cast = |bx: &mut Bx, val, ty| { if ty == bx.cx().type_i1() { bx.trunc(val, ty) } else { @@ -251,14 +253,15 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> { } }; - // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. match val { OperandValue::Immediate(ref mut llval) => { - *llval = bitcast(bx, *llval, bx.cx().immediate_backend_type(field)); + *llval = to_immediate_or_cast(bx, *llval, bx.cx().immediate_backend_type(field)); } OperandValue::Pair(ref mut a, ref mut b) => { - *a = bitcast(bx, *a, bx.cx().scalar_pair_element_backend_type(field, 0, true)); - *b = bitcast(bx, *b, bx.cx().scalar_pair_element_backend_type(field, 1, true)); + *a = to_immediate_or_cast(bx, *a, bx.cx() + .scalar_pair_element_backend_type(field, 0, true)); + *b = to_immediate_or_cast(bx, *b, bx.cx() + .scalar_pair_element_backend_type(field, 1, true)); } OperandValue::Ref(..) => bug!() } From 88d60941da317d8e9deee34d2ed5e8dbb54f928c Mon Sep 17 00:00:00 2001 From: Axary Date: Tue, 20 Nov 2018 14:43:16 +0100 Subject: [PATCH 0075/1984] improve error note --- src/libsyntax/parse/parser.rs | 2 +- src/test/ui/invalid-self-argument/bare-fn-start.rs | 2 +- src/test/ui/invalid-self-argument/bare-fn-start.stderr | 2 +- src/test/ui/invalid-self-argument/bare-fn.rs | 2 +- src/test/ui/invalid-self-argument/bare-fn.stderr | 2 +- src/test/ui/invalid-self-argument/trait-fn.rs | 2 +- src/test/ui/invalid-self-argument/trait-fn.stderr | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 18929af4718..e4a4c1f5a7c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1828,7 +1828,7 @@ impl<'a> Parser<'a> { let mut err = self.struct_span_err(self.prev_span, "unexpected `self` argument in function"); err.span_label(self.prev_span, - "`self` is only valid as the first argument of a trait function"); + "`self` is only valid as the first argument of an associated function"); return Err(err); } diff --git a/src/test/ui/invalid-self-argument/bare-fn-start.rs b/src/test/ui/invalid-self-argument/bare-fn-start.rs index a84fe55502d..741ba5f41ce 100644 --- a/src/test/ui/invalid-self-argument/bare-fn-start.rs +++ b/src/test/ui/invalid-self-argument/bare-fn-start.rs @@ -1,5 +1,5 @@ fn a(&self) { } //~^ ERROR unexpected `self` argument in function -//~| NOTE `self` is only valid as the first argument of a trait function +//~| NOTE `self` is only valid as the first argument of an associated function fn main() { } diff --git a/src/test/ui/invalid-self-argument/bare-fn-start.stderr b/src/test/ui/invalid-self-argument/bare-fn-start.stderr index d0eca1a9e5c..6a878b619d8 100644 --- a/src/test/ui/invalid-self-argument/bare-fn-start.stderr +++ b/src/test/ui/invalid-self-argument/bare-fn-start.stderr @@ -2,7 +2,7 @@ error: unexpected `self` argument in function --> $DIR/bare-fn-start.rs:1:7 | LL | fn a(&self) { } - | ^^^^ `self` is only valid as the first argument of a trait function + | ^^^^ `self` is only valid as the first argument of an associated function error: aborting due to previous error diff --git a/src/test/ui/invalid-self-argument/bare-fn.rs b/src/test/ui/invalid-self-argument/bare-fn.rs index 27e56a53713..704fa996ca6 100644 --- a/src/test/ui/invalid-self-argument/bare-fn.rs +++ b/src/test/ui/invalid-self-argument/bare-fn.rs @@ -1,5 +1,5 @@ fn b(foo: u32, &mut self) { } //~^ ERROR unexpected `self` argument in function -//~| NOTE `self` is only valid as the first argument of a trait function +//~| NOTE `self` is only valid as the first argument of an associated function fn main() { } diff --git a/src/test/ui/invalid-self-argument/bare-fn.stderr b/src/test/ui/invalid-self-argument/bare-fn.stderr index bd6c598c88a..b13f746a4ec 100644 --- a/src/test/ui/invalid-self-argument/bare-fn.stderr +++ b/src/test/ui/invalid-self-argument/bare-fn.stderr @@ -2,7 +2,7 @@ error: unexpected `self` argument in function --> $DIR/bare-fn.rs:1:21 | LL | fn b(foo: u32, &mut self) { } - | ^^^^ `self` is only valid as the first argument of a trait function + | ^^^^ `self` is only valid as the first argument of an associated function error: aborting due to previous error diff --git a/src/test/ui/invalid-self-argument/trait-fn.rs b/src/test/ui/invalid-self-argument/trait-fn.rs index e2107e4d867..31e867bc764 100644 --- a/src/test/ui/invalid-self-argument/trait-fn.rs +++ b/src/test/ui/invalid-self-argument/trait-fn.rs @@ -3,7 +3,7 @@ struct Foo {} impl Foo { fn c(foo: u32, self) {} //~^ ERROR unexpected `self` argument in function - //~| NOTE `self` is only valid as the first argument of a trait function + //~| NOTE `self` is only valid as the first argument of an associated function fn good(&mut self, foo: u32) {} } diff --git a/src/test/ui/invalid-self-argument/trait-fn.stderr b/src/test/ui/invalid-self-argument/trait-fn.stderr index d056e53b95c..b3c2cc5b5eb 100644 --- a/src/test/ui/invalid-self-argument/trait-fn.stderr +++ b/src/test/ui/invalid-self-argument/trait-fn.stderr @@ -2,7 +2,7 @@ error: unexpected `self` argument in function --> $DIR/trait-fn.rs:4:20 | LL | fn c(foo: u32, self) {} - | ^^^^ `self` is only valid as the first argument of a trait function + | ^^^^ `self` is only valid as the first argument of an associated function error: aborting due to previous error From 6eeedbcd70855b45cf41ef14bc91a15f0ee67c7c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 20 Nov 2018 15:08:26 +0100 Subject: [PATCH 0076/1984] generator fields are not necessarily initialized --- src/librustc_mir/interpret/visitor.rs | 33 ++++++++++++++++++--------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs index f0a71242599..505195763d0 100644 --- a/src/librustc_mir/interpret/visitor.rs +++ b/src/librustc_mir/interpret/visitor.rs @@ -142,6 +142,7 @@ macro_rules! make_value_visitor { self.walk_value(v) } /// Visit the given value as a union. No automatic recursion can happen here. + /// Also called for the fields of a generator, which may or may not be initialized. #[inline(always)] fn visit_union(&mut self, _v: Self::V) -> EvalResult<'tcx> { @@ -291,17 +292,28 @@ macro_rules! make_value_visitor { // use that as an unambiguous signal for detecting primitives. Make sure // we did not miss any primitive. debug_assert!(fields > 0); - self.visit_union(v)?; + self.visit_union(v) }, layout::FieldPlacement::Arbitrary { ref offsets, .. } => { - // FIXME: We collect in a vec because otherwise there are lifetime errors: - // Projecting to a field needs (mutable!) access to `ecx`. - let fields: Vec> = - (0..offsets.len()).map(|i| { - v.project_field(self.ecx(), i as u64) - }) - .collect(); - self.visit_aggregate(v, fields.into_iter())?; + // Special handling needed for generators: All but the first field + // (which is the state) are actually implicitly `MaybeUninit`, i.e., + // they may or may not be initialized, so we cannot visit them. + match v.layout().ty.sty { + ty::Generator(..) => { + let field = v.project_field(self.ecx(), 0)?; + self.visit_aggregate(v, std::iter::once(Ok(field))) + } + _ => { + // FIXME: We collect in a vec because otherwise there are lifetime + // errors: Projecting to a field needs access to `ecx`. + let fields: Vec> = + (0..offsets.len()).map(|i| { + v.project_field(self.ecx(), i as u64) + }) + .collect(); + self.visit_aggregate(v, fields.into_iter()) + } + } }, layout::FieldPlacement::Array { .. } => { // Let's get an mplace first. @@ -317,10 +329,9 @@ macro_rules! make_value_visitor { .map(|f| f.and_then(|f| { Ok(Value::from_mem_place(f)) })); - self.visit_aggregate(v, iter)?; + self.visit_aggregate(v, iter) } } - Ok(()) } } } From 033cbfec4d3bb23948a99379f8d63b7cfe5eed45 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Tue, 20 Nov 2018 09:34:15 -0500 Subject: [PATCH 0077/1984] Incorporate `dyn` into more comments and docs. --- src/liballoc/boxed.rs | 16 ++++++++-------- src/liballoc/rc.rs | 4 ++-- src/libcore/raw.rs | 2 +- src/librustc/mir/mod.rs | 2 +- src/librustc/ty/adjustment.rs | 2 +- src/librustc/ty/util.rs | 2 +- src/librustc_codegen_ssa/meth.rs | 2 +- src/libstd/fs.rs | 4 ++-- src/test/run-pass/string-box-error.rs | 3 ++- 9 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 63b262d1f3d..c3a84bf778d 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -489,7 +489,7 @@ impl Box { /// ``` /// use std::any::Any; /// - /// fn print_if_string(value: Box) { + /// fn print_if_string(value: Box) { /// if let Ok(string) = value.downcast::() { /// println!("String ({}): {}", string.len(), string); /// } @@ -523,7 +523,7 @@ impl Box { /// ``` /// use std::any::Any; /// - /// fn print_if_string(value: Box) { + /// fn print_if_string(value: Box) { /// if let Ok(string) = value.downcast::() { /// println!("String ({}): {}", string.len(), string); /// } @@ -618,10 +618,10 @@ impl FusedIterator for Box {} /// `FnBox` is a version of the `FnOnce` intended for use with boxed /// closure objects. The idea is that where one would normally store a -/// `Box` in a data structure, you should use -/// `Box`. The two traits behave essentially the same, except +/// `Box` in a data structure, you should use +/// `Box`. The two traits behave essentially the same, except /// that a `FnBox` closure can only be called if it is boxed. (Note -/// that `FnBox` may be deprecated in the future if `Box` +/// that `FnBox` may be deprecated in the future if `Box` /// closures become directly usable.) /// /// # Examples @@ -629,7 +629,7 @@ impl FusedIterator for Box {} /// Here is a snippet of code which creates a hashmap full of boxed /// once closures and then removes them one by one, calling each /// closure as it is removed. Note that the type of the closures -/// stored in the map is `Box i32>` and not `Box i32>` and not `Box i32>`. /// /// ``` @@ -638,8 +638,8 @@ impl FusedIterator for Box {} /// use std::boxed::FnBox; /// use std::collections::HashMap; /// -/// fn make_map() -> HashMap i32>> { -/// let mut map: HashMap i32>> = HashMap::new(); +/// fn make_map() -> HashMap i32>> { +/// let mut map: HashMap i32>> = HashMap::new(); /// map.insert(1, Box::new(|| 22)); /// map.insert(2, Box::new(|| 44)); /// map diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index bb52d7990ff..12c19912662 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -634,7 +634,7 @@ impl Rc { impl Rc { #[inline] #[stable(feature = "rc_downcast", since = "1.29.0")] - /// Attempt to downcast the `Rc` to a concrete type. + /// Attempt to downcast the `Rc` to a concrete type. /// /// # Examples /// @@ -642,7 +642,7 @@ impl Rc { /// use std::any::Any; /// use std::rc::Rc; /// - /// fn print_if_string(value: Rc) { + /// fn print_if_string(value: Rc) { /// if let Ok(string) = value.downcast::() { /// println!("String ({}): {}", string.len(), string); /// } diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index a95f05227fb..b7597795b5e 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -21,7 +21,7 @@ /// The representation of a trait object like `&SomeTrait`. /// /// This struct has the same layout as types like `&SomeTrait` and -/// `Box`. The [Trait Objects chapter of the +/// `Box`. The [Trait Objects chapter of the /// Book][moreinfo] contains more details about the precise nature of /// these internals. /// diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index d8e45c881f5..acc03bd4a48 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2207,7 +2207,7 @@ pub enum CastKind { /// "Unsize" -- convert a thin-or-fat pointer to a fat pointer. /// codegen must figure out the details once full monomorphization /// is known. For example, this could be used to cast from a - /// `&[i32;N]` to a `&[i32]`, or a `Box` to a `Box` + /// `&[i32;N]` to a `&[i32]`, or a `Box` to a `Box` /// (presuming `T: Trait`). Unsize, } diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index 3263da8fda3..83521c5f724 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -48,7 +48,7 @@ use ty::subst::Substs; /// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about /// the underlying conversions from `[i32; 4]` to `[i32]`. /// -/// 3. Coercing a `Box` to `Box` is an interesting special case. In +/// 3. Coercing a `Box` to `Box` is an interesting special case. In /// that case, we have the pointer we need coming in, so there are no /// autoderefs, and no autoref. Instead we just do the `Unsize` transformation. /// At some point, of course, `Box` should move out of the compiler, in which diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 3d0c54d6b0a..0d756aa0781 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -303,7 +303,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Same as applying struct_tail on `source` and `target`, but only /// keeps going as long as the two types are instances of the same /// structure definitions. - /// For `(Foo>, Foo)`, the result will be `(Foo, Trait)`, + /// For `(Foo>, Foo)`, the result will be `(Foo, Trait)`, /// whereas struct_tail produces `T`, and `Trait`, respectively. pub fn struct_lockstep_tails(self, source: Ty<'tcx>, diff --git a/src/librustc_codegen_ssa/meth.rs b/src/librustc_codegen_ssa/meth.rs index 06c4f7a87d8..24be932141c 100644 --- a/src/librustc_codegen_ssa/meth.rs +++ b/src/librustc_codegen_ssa/meth.rs @@ -74,7 +74,7 @@ impl<'a, 'tcx: 'a> VirtualIndex { /// The vtables are cached instead of created on every call. /// /// The `trait_ref` encodes the erased self type. Hence if we are -/// making an object `Foo` from a value of type `Foo`, then +/// making an object `Foo` from a value of type `Foo`, then /// `trait_ref` would map `T:Trait`. pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( cx: &Cx, diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index f4703dec187..92678dd5ced 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -256,7 +256,7 @@ fn initial_buffer_size(file: &File) -> usize { /// use std::fs; /// use std::net::SocketAddr; /// -/// fn main() -> Result<(), Box> { +/// fn main() -> Result<(), Box> { /// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?; /// Ok(()) /// } @@ -298,7 +298,7 @@ pub fn read>(path: P) -> io::Result> { /// use std::fs; /// use std::net::SocketAddr; /// -/// fn main() -> Result<(), Box> { +/// fn main() -> Result<(), Box> { /// let foo: SocketAddr = fs::read_to_string("address.txt")?.parse()?; /// Ok(()) /// } diff --git a/src/test/run-pass/string-box-error.rs b/src/test/run-pass/string-box-error.rs index a80d9a05935..5d8a664b93d 100644 --- a/src/test/run-pass/string-box-error.rs +++ b/src/test/run-pass/string-box-error.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Ensure that both `Box` and `Box` can be obtained from `String`. +// Ensure that both `Box` and `Box` can be +// obtained from `String`. use std::error::Error; From 7f1077700c019b2dc8d651528ecad106c9267858 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 20 Nov 2018 15:55:23 +0100 Subject: [PATCH 0078/1984] fix comment --- src/librustc_mir/interpret/visitor.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs index 505195763d0..a645e067322 100644 --- a/src/librustc_mir/interpret/visitor.rs +++ b/src/librustc_mir/interpret/visitor.rs @@ -142,7 +142,6 @@ macro_rules! make_value_visitor { self.walk_value(v) } /// Visit the given value as a union. No automatic recursion can happen here. - /// Also called for the fields of a generator, which may or may not be initialized. #[inline(always)] fn visit_union(&mut self, _v: Self::V) -> EvalResult<'tcx> { From 6befe6784f37d953884ef05982b41c3a11932170 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 20 Nov 2018 16:19:24 +0100 Subject: [PATCH 0079/1984] treat generator fields like unions --- src/librustc_mir/interpret/visitor.rs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs index a645e067322..81e56f3115d 100644 --- a/src/librustc_mir/interpret/visitor.rs +++ b/src/librustc_mir/interpret/visitor.rs @@ -158,7 +158,9 @@ macro_rules! make_value_visitor { ) -> EvalResult<'tcx> { self.walk_aggregate(v, fields) } - /// Called each time we recurse down to a field, passing in old and new value. + + /// Called each time we recurse down to a field of a "product-like" aggregate + /// (structs, tuples, arrays and the like, but not enums), passing in old and new value. /// This gives the visitor the chance to track the stack of nested fields that /// we are descending through. #[inline(always)] @@ -171,6 +173,19 @@ macro_rules! make_value_visitor { self.visit_value(new_val) } + /// Called for recursing into the field of a generator. These are not known to be + /// initialized, so we treat them like unions. + #[inline(always)] + fn visit_generator_field( + &mut self, + _old_val: Self::V, + _field: usize, + new_val: Self::V, + ) -> EvalResult<'tcx> { + self.visit_union(new_val) + } + + /// Called when recursing into an enum variant. #[inline(always)] fn visit_variant( &mut self, @@ -300,7 +315,12 @@ macro_rules! make_value_visitor { match v.layout().ty.sty { ty::Generator(..) => { let field = v.project_field(self.ecx(), 0)?; - self.visit_aggregate(v, std::iter::once(Ok(field))) + self.visit_aggregate(v, std::iter::once(Ok(field)))?; + for i in 1..offsets.len() { + let field = v.project_field(self.ecx(), i as u64)?; + self.visit_generator_field(v, i, field)?; + } + Ok(()) } _ => { // FIXME: We collect in a vec because otherwise there are lifetime From 8a0909df79d30c2d893dc6b6bfc2ec5667dc28cc Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 20 Nov 2018 17:30:29 +0100 Subject: [PATCH 0080/1984] Remove incorrect doc comment --- src/librustc_codegen_ssa/mono_item.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/librustc_codegen_ssa/mono_item.rs b/src/librustc_codegen_ssa/mono_item.rs index 53acb3e376c..8fe89791969 100644 --- a/src/librustc_codegen_ssa/mono_item.rs +++ b/src/librustc_codegen_ssa/mono_item.rs @@ -8,12 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Walks the crate looking for items/impl-items/trait-items that have -//! either a `rustc_symbol_name` or `rustc_item_path` attribute and -//! generates an error giving, respectively, the symbol name or -//! item-path. This is used for unit testing the code that generates -//! paths etc in all kinds of annoying scenarios. - use base; use rustc::hir; use rustc::hir::def::Def; From 9ce7b11e7c6ac970c4a507f27ea340d4dd4e8960 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 20 Nov 2018 17:32:46 +0100 Subject: [PATCH 0081/1984] Remove incorrect doc comment in rustc_mir::monomorphize::item --- src/librustc_mir/monomorphize/item.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 9d69a5669b1..9c90e5ffd3c 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -8,12 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Walks the crate looking for items/impl-items/trait-items that have -//! either a `rustc_symbol_name` or `rustc_item_path` attribute and -//! generates an error giving, respectively, the symbol name or -//! item-path. This is used for unit testing the code that generates -//! paths etc in all kinds of annoying scenarios. - use monomorphize::Instance; use rustc::hir; use rustc::hir::def_id::DefId; From 48aae09e9fe0a5574f59867610a9005c68ff5c19 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sun, 11 Nov 2018 12:13:59 +0100 Subject: [PATCH 0082/1984] Add std::iter::unfold --- src/libcore/iter/mod.rs | 2 + src/libcore/iter/sources.rs | 76 +++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 509068843d1..5ac8b2d2895 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -339,6 +339,8 @@ pub use self::sources::{RepeatWith, repeat_with}; pub use self::sources::{Empty, empty}; #[stable(feature = "iter_once", since = "1.2.0")] pub use self::sources::{Once, once}; +#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +pub use self::sources::{Unfold, unfold}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend}; diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index 7fa3a4bcce7..a209b90ace1 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -386,3 +386,79 @@ impl FusedIterator for Once {} pub fn once(value: T) -> Once { Once { inner: Some(value).into_iter() } } + +/// Creates a new iterator where each iteration calls the provided closure +/// `F: FnMut(&mut St) -> Option`. +/// +/// This allows creating a custom iterator with any behavior +/// without using the more verbose syntax of creating a dedicated type +/// and implementing the `Iterator` trait for it. +/// +/// In addition to its captures and environment, +/// the closure is given a mutable reference to some state +/// that is preserved across iterations. +/// That state starts as the given `initial_state` value. +/// +/// Note that the `Unfold` iterator doesn’t make assumptions about the behavior of the closure, +/// and therefore conservatively does not implement [`FusedIterator`], +/// or override [`Iterator::size_hint`] from its default `(0, None)`. +/// +/// [`FusedIterator`]: trait.FusedIterator.html +/// [`Iterator::size_hint`]: trait.Iterator.html#method.size_hint +/// +/// # Examples +/// +/// Let’s re-implement the counter iterator from [module-level documentation]: +/// +/// [module-level documentation]: index.html +/// +/// ``` +/// #![feature(iter_unfold)] +/// let counter = std::iter::unfold(0, |count| { +/// // increment our count. This is why we started at zero. +/// *count += 1; +/// +/// // check to see if we've finished counting or not. +/// if *count < 6 { +/// Some(*count) +/// } else { +/// None +/// } +/// }); +/// assert_eq!(counter.collect::>(), &[1, 2, 3, 4, 5]); +/// ``` +#[inline] +#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +pub fn unfold(initial_state: St, f: F) -> Unfold + where F: FnMut(&mut St) -> Option +{ + Unfold { + state: initial_state, + f, + } +} + +/// An iterator where each iteration calls the provided closure `F: FnMut(&mut St) -> Option`. +/// +/// This `struct` is created by the [`unfold`] function. +/// See its documentation for more. +/// +/// [`unfold`]: fn.unfold.html +#[derive(Copy, Clone, Debug)] +#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +pub struct Unfold { + state: St, + f: F, +} + +#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +impl Iterator for Unfold + where F: FnMut(&mut St) -> Option +{ + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + (self.f)(&mut self.state) + } +} From 544ad37753184c387fd235dea8bd4c3fba22bd74 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 15 Nov 2018 13:21:25 +0100 Subject: [PATCH 0083/1984] Unfold: Debug without F: Debug --- src/libcore/iter/sources.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index a209b90ace1..d769c9c80a0 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -444,7 +444,7 @@ pub fn unfold(initial_state: St, f: F) -> Unfold /// See its documentation for more. /// /// [`unfold`]: fn.unfold.html -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone)] #[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] pub struct Unfold { state: St, @@ -462,3 +462,12 @@ impl Iterator for Unfold (self.f)(&mut self.state) } } + +#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +impl fmt::Debug for Unfold { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Unfold") + .field("state", &self.state) + .finish() + } +} From 22228186c0d373774a117375c2c264024bfd4b48 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 15 Nov 2018 14:22:21 +0100 Subject: [PATCH 0084/1984] `Copy` is best avoided on iterators --- src/libcore/iter/sources.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index d769c9c80a0..93c64c748c9 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -444,7 +444,7 @@ pub fn unfold(initial_state: St, f: F) -> Unfold /// See its documentation for more. /// /// [`unfold`]: fn.unfold.html -#[derive(Copy, Clone)] +#[derive(Clone)] #[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] pub struct Unfold { state: St, From 641c4909e4de0334c83372b4795388d98cfd257a Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 15 Nov 2018 14:23:20 +0100 Subject: [PATCH 0085/1984] Add std::iter::successors --- src/libcore/iter/mod.rs | 2 +- src/libcore/iter/sources.rs | 76 +++++++++++++++++++++++++++++++++++++ src/libcore/tests/iter.rs | 11 ++++++ src/libcore/tests/lib.rs | 1 + 4 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 5ac8b2d2895..5f45cd927b8 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -340,7 +340,7 @@ pub use self::sources::{Empty, empty}; #[stable(feature = "iter_once", since = "1.2.0")] pub use self::sources::{Once, once}; #[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] -pub use self::sources::{Unfold, unfold}; +pub use self::sources::{Unfold, unfold, Successors, successors}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend}; diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index 93c64c748c9..7f559652392 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -471,3 +471,79 @@ impl fmt::Debug for Unfold { .finish() } } + +/// Creates a new iterator where each successive item is computed based on the preceding one. +/// +/// The iterator starts with the given first item (if any) +/// and calls the given `FnMut(&T) -> Option` closure to compute each item’s successor. +/// +/// ``` +/// #![feature(iter_unfold)] +/// use std::iter::successors; +/// +/// let powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10)); +/// assert_eq!(powers_of_10.collect::>(), &[1, 10, 100, 1_000, 10_000]); +/// ``` +#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +pub fn successors(first: Option, succ: F) -> Successors + where F: FnMut(&T) -> Option +{ + // If this function returned `impl Iterator` + // it could be based on `unfold` and not need a dedicated type. + // However having a named `Successors` type allows it to be `Clone` when `T` and `F` are. + Successors { + next: first, + succ, + } +} + +/// An new iterator where each successive item is computed based on the preceding one. +/// +/// This `struct` is created by the [`successors`] function. +/// See its documentation for more. +/// +/// [`successors`]: fn.successors.html +#[derive(Clone)] +#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +pub struct Successors { + next: Option, + succ: F, +} + +#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +impl Iterator for Successors + where F: FnMut(&T) -> Option +{ + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.next.take().map(|item| { + self.next = (self.succ)(&item); + item + }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.next.is_some() { + (1, None) + } else { + (0, Some(0)) + } + } +} + +#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +impl FusedIterator for Successors + where F: FnMut(&T) -> Option +{} + +#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +impl fmt::Debug for Successors { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Successors") + .field("next", &self.next) + .finish() + } +} diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index ec09071b3d0..495483db555 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1759,6 +1759,17 @@ fn test_repeat_with_take_collect() { assert_eq!(v, vec![1, 2, 4, 8, 16]); } +#[test] +fn test_successors() { + let mut powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10)); + assert_eq!(powers_of_10.by_ref().collect::>(), &[1, 10, 100, 1_000, 10_000]); + assert_eq!(powers_of_10.next(), None); + + let mut empty = successors(None::, |_| unimplemented!()); + assert_eq!(empty.next(), None); + assert_eq!(empty.next(), None); +} + #[test] fn test_fuse() { let mut it = 0..3; diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 5ac89912268..7d62b4fa90f 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -19,6 +19,7 @@ #![feature(flt2dec)] #![feature(fmt_internals)] #![feature(hashmap_internals)] +#![feature(iter_unfold)] #![feature(pattern)] #![feature(range_is_empty)] #![feature(raw)] From 8a5bbd9a4e85e1383b87796f871a9020410bbd10 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 15 Nov 2018 14:33:47 +0100 Subject: [PATCH 0086/1984] Add tracking issue for unfold and successors --- src/libcore/iter/mod.rs | 2 +- src/libcore/iter/sources.rs | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 5f45cd927b8..8ae4b53da95 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -339,7 +339,7 @@ pub use self::sources::{RepeatWith, repeat_with}; pub use self::sources::{Empty, empty}; #[stable(feature = "iter_once", since = "1.2.0")] pub use self::sources::{Once, once}; -#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +#[unstable(feature = "iter_unfold", issue = "55977")] pub use self::sources::{Unfold, unfold, Successors, successors}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index 7f559652392..6d35d546415 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -428,7 +428,7 @@ pub fn once(value: T) -> Once { /// assert_eq!(counter.collect::>(), &[1, 2, 3, 4, 5]); /// ``` #[inline] -#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +#[unstable(feature = "iter_unfold", issue = "55977")] pub fn unfold(initial_state: St, f: F) -> Unfold where F: FnMut(&mut St) -> Option { @@ -445,13 +445,13 @@ pub fn unfold(initial_state: St, f: F) -> Unfold /// /// [`unfold`]: fn.unfold.html #[derive(Clone)] -#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +#[unstable(feature = "iter_unfold", issue = "55977")] pub struct Unfold { state: St, f: F, } -#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +#[unstable(feature = "iter_unfold", issue = "55977")] impl Iterator for Unfold where F: FnMut(&mut St) -> Option { @@ -463,7 +463,7 @@ impl Iterator for Unfold } } -#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +#[unstable(feature = "iter_unfold", issue = "55977")] impl fmt::Debug for Unfold { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Unfold") @@ -484,7 +484,7 @@ impl fmt::Debug for Unfold { /// let powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10)); /// assert_eq!(powers_of_10.collect::>(), &[1, 10, 100, 1_000, 10_000]); /// ``` -#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +#[unstable(feature = "iter_unfold", issue = "55977")] pub fn successors(first: Option, succ: F) -> Successors where F: FnMut(&T) -> Option { @@ -504,13 +504,13 @@ pub fn successors(first: Option, succ: F) -> Successors /// /// [`successors`]: fn.successors.html #[derive(Clone)] -#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +#[unstable(feature = "iter_unfold", issue = "55977")] pub struct Successors { next: Option, succ: F, } -#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +#[unstable(feature = "iter_unfold", issue = "55977")] impl Iterator for Successors where F: FnMut(&T) -> Option { @@ -534,12 +534,12 @@ impl Iterator for Successors } } -#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +#[unstable(feature = "iter_unfold", issue = "55977")] impl FusedIterator for Successors where F: FnMut(&T) -> Option {} -#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")] +#[unstable(feature = "iter_unfold", issue = "55977")] impl fmt::Debug for Successors { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Successors") From a4279a07e29091fd8a72b13b2109c8969e713ffd Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 20 Nov 2018 18:22:26 +0100 Subject: [PATCH 0087/1984] Capitalize --- src/libcore/iter/mod.rs | 4 ++-- src/libcore/iter/sources.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 8ae4b53da95..62e1f9fcb64 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -112,10 +112,10 @@ //! //! // next() is the only required method //! fn next(&mut self) -> Option { -//! // increment our count. This is why we started at zero. +//! // Increment our count. This is why we started at zero. //! self.count += 1; //! -//! // check to see if we've finished counting or not. +//! // Check to see if we've finished counting or not. //! if self.count < 6 { //! Some(self.count) //! } else { diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index 6d35d546415..f6a4a7a6fa8 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -415,10 +415,10 @@ pub fn once(value: T) -> Once { /// ``` /// #![feature(iter_unfold)] /// let counter = std::iter::unfold(0, |count| { -/// // increment our count. This is why we started at zero. +/// // Increment our count. This is why we started at zero. /// *count += 1; /// -/// // check to see if we've finished counting or not. +/// // Check to see if we've finished counting or not. /// if *count < 6 { /// Some(*count) /// } else { From b99f9f775c59de7223e810b303e56b39f7bbaf03 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 20 Nov 2018 21:48:13 +0000 Subject: [PATCH 0088/1984] Enclose type in backticks for "non-exhaustive patterns" error This makes the error style consistent with the convention in error messages. --- src/librustc_mir/hair/pattern/check_match.rs | 2 +- src/test/ui/error-codes/E0004-2.stderr | 2 +- src/test/ui/issues/issue-3096-1.stderr | 2 +- src/test/ui/issues/issue-3096-2.stderr | 2 +- .../ui/uninhabited/uninhabited-matches-feature-gated.stderr | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index bafabe4e997..a6bd36e582f 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -234,7 +234,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { if !scrutinee_is_uninhabited { // We know the type is inhabited, so this must be wrong let mut err = create_e0004(self.tcx.sess, scrut.span, - format!("non-exhaustive patterns: type {} \ + format!("non-exhaustive patterns: type `{}` \ is non-empty", pat_ty)); span_help!(&mut err, scrut.span, diff --git a/src/test/ui/error-codes/E0004-2.stderr b/src/test/ui/error-codes/E0004-2.stderr index 900812787bc..2d46196ddda 100644 --- a/src/test/ui/error-codes/E0004-2.stderr +++ b/src/test/ui/error-codes/E0004-2.stderr @@ -1,4 +1,4 @@ -error[E0004]: non-exhaustive patterns: type std::option::Option is non-empty +error[E0004]: non-exhaustive patterns: type `std::option::Option` is non-empty --> $DIR/E0004-2.rs:14:11 | LL | match x { } //~ ERROR E0004 diff --git a/src/test/ui/issues/issue-3096-1.stderr b/src/test/ui/issues/issue-3096-1.stderr index b2bfe6b5e8c..f0782bd9738 100644 --- a/src/test/ui/issues/issue-3096-1.stderr +++ b/src/test/ui/issues/issue-3096-1.stderr @@ -1,4 +1,4 @@ -error[E0004]: non-exhaustive patterns: type () is non-empty +error[E0004]: non-exhaustive patterns: type `()` is non-empty --> $DIR/issue-3096-1.rs:12:11 | LL | match () { } //~ ERROR non-exhaustive diff --git a/src/test/ui/issues/issue-3096-2.stderr b/src/test/ui/issues/issue-3096-2.stderr index bb9dfabe7be..e0fa641ff39 100644 --- a/src/test/ui/issues/issue-3096-2.stderr +++ b/src/test/ui/issues/issue-3096-2.stderr @@ -1,4 +1,4 @@ -error[E0004]: non-exhaustive patterns: type *const bottom is non-empty +error[E0004]: non-exhaustive patterns: type `*const bottom` is non-empty --> $DIR/issue-3096-2.rs:15:11 | LL | match x { } //~ ERROR non-exhaustive patterns diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr index 83fd736a997..f4974b8fa38 100644 --- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr +++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr @@ -4,7 +4,7 @@ error[E0004]: non-exhaustive patterns: `Err(_)` not covered LL | let _ = match x { //~ ERROR non-exhaustive | ^ pattern `Err(_)` not covered -error[E0004]: non-exhaustive patterns: type &Void is non-empty +error[E0004]: non-exhaustive patterns: type `&Void` is non-empty --> $DIR/uninhabited-matches-feature-gated.rs:20:19 | LL | let _ = match x {}; //~ ERROR non-exhaustive @@ -16,7 +16,7 @@ help: ensure that all possible cases are being handled, possibly by adding wildc LL | let _ = match x {}; //~ ERROR non-exhaustive | ^ -error[E0004]: non-exhaustive patterns: type (Void,) is non-empty +error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty --> $DIR/uninhabited-matches-feature-gated.rs:23:19 | LL | let _ = match x {}; //~ ERROR non-exhaustive @@ -28,7 +28,7 @@ help: ensure that all possible cases are being handled, possibly by adding wildc LL | let _ = match x {}; //~ ERROR non-exhaustive | ^ -error[E0004]: non-exhaustive patterns: type [Void; 1] is non-empty +error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty --> $DIR/uninhabited-matches-feature-gated.rs:26:19 | LL | let _ = match x {}; //~ ERROR non-exhaustive From 25d0418bd74711b170c874fefe12e68ad83016c8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 20 Nov 2018 15:56:19 -0800 Subject: [PATCH 0089/1984] ci: Download clang/lldb from tarballs Hopefully will speed up CI slightly! --- src/ci/init_repo.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh index f2664e6d196..8345ab3bc33 100755 --- a/src/ci/init_repo.sh +++ b/src/ci/init_repo.sh @@ -55,6 +55,7 @@ function fetch_submodule { } included="src/llvm src/llvm-emscripten src/doc/book src/doc/rust-by-example" +included="$included src/tools/lld src/tools/clang src/tools/lldb" modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)" modules=($modules) use_git="" From 1e4cf740cfaf5332722ae6ff717ceaed181a4caf Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 21 Nov 2018 03:39:41 +0300 Subject: [PATCH 0090/1984] resolve: Make "empty import canaries" invisible from other crates --- src/librustc_resolve/resolve_imports.rs | 5 ++++- src/test/ui/imports/auxiliary/issue-55811.rs | 5 +++++ src/test/ui/imports/issue-55811.rs | 6 ++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/imports/auxiliary/issue-55811.rs create mode 100644 src/test/ui/imports/issue-55811.rs diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 9e5036b6e50..c2ba3048c1b 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1164,7 +1164,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { None => continue, }; - if binding.is_import() || binding.is_macro_def() { + // Filter away "empty import canaries". + let is_non_canary_import = + binding.is_import() && binding.vis != ty::Visibility::Invisible; + if is_non_canary_import || binding.is_macro_def() { let def = binding.def(); if def != Def::Err { if let Some(def_id) = def.opt_def_id() { diff --git a/src/test/ui/imports/auxiliary/issue-55811.rs b/src/test/ui/imports/auxiliary/issue-55811.rs new file mode 100644 index 00000000000..877e4cdb0bd --- /dev/null +++ b/src/test/ui/imports/auxiliary/issue-55811.rs @@ -0,0 +1,5 @@ +mod m {} + +// These two imports should not conflict when this crate is loaded from some other crate. +use m::{}; +use m::{}; diff --git a/src/test/ui/imports/issue-55811.rs b/src/test/ui/imports/issue-55811.rs new file mode 100644 index 00000000000..95316777fab --- /dev/null +++ b/src/test/ui/imports/issue-55811.rs @@ -0,0 +1,6 @@ +// compile-pass +// aux-build:issue-55811.rs + +extern crate issue_55811; + +fn main() {} From 240a55ce50531f3bc237027593205d3b857eba33 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 20 Nov 2018 07:40:31 -0500 Subject: [PATCH 0091/1984] update books --- src/doc/book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/book b/src/doc/book index e871c459892..616fe4172b6 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit e871c4598925594421d63e929fee292e6e071f97 +Subproject commit 616fe4172b688393aeee5f34935cc25733c9c062 diff --git a/src/doc/nomicon b/src/doc/nomicon index 7f7a597b47e..f8a4e96feb2 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 7f7a597b47ed6c35c2a0f0ee6a69050fe2d5e013 +Subproject commit f8a4e96feb2e5a6ed1ef170ad40e3509a7755cb4 diff --git a/src/doc/reference b/src/doc/reference index b9fb838054b..60077efda31 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit b9fb838054b8441223c22eeae5b6d8e498071cd0 +Subproject commit 60077efda319c95a89fe39609803c5433567adbf diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index bc342a475c0..2ce92beabb9 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit bc342a475c09b6df8004d518382e6d5b6bcb49f7 +Subproject commit 2ce92beabb912d417a7314d6da83ac9b50dc2afb From 0579ef0166e7ce493e57f17121f7b5ef809265b1 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 20 Nov 2018 14:57:56 -0500 Subject: [PATCH 0092/1984] fix rustbuild to build all the books --- src/bootstrap/doc.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 7623ca1e27e..f9b19ffb10d 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -260,22 +260,31 @@ impl Step for TheBook { let compiler = self.compiler; let target = self.target; let name = self.name; - // build book first edition + + // build book builder.ensure(Rustbook { target, - name: INTERNER.intern_string(format!("{}/first-edition", name)), + name: INTERNER.intern_string(name.to_string()), }); - // build book second edition + // building older edition redirects + + let source_name = format!("{}/first-edition", name); builder.ensure(Rustbook { target, - name: INTERNER.intern_string(format!("{}/second-edition", name)), + name: INTERNER.intern_string(source_name), }); - // build book 2018 edition + let source_name = format!("{}/second-edition", name); builder.ensure(Rustbook { target, - name: INTERNER.intern_string(format!("{}/2018-edition", name)), + name: INTERNER.intern_string(source_name), + }); + + let source_name = format!("{}/2018-edition", name); + builder.ensure(Rustbook { + target, + name: INTERNER.intern_string(source_name), }); // build the version info page and CSS @@ -284,11 +293,6 @@ impl Step for TheBook { target, }); - // build the index page - let index = format!("{}/index.md", name); - builder.info(&format!("Documenting book index ({})", target)); - invoke_rustdoc(builder, compiler, target, &index); - // build the redirect pages builder.info(&format!("Documenting book redirect pages ({})", target)); for file in t!(fs::read_dir(builder.src.join("src/doc/book/redirects"))) { From 57b7d55591d0a4a0d9aa16afa0f202427aa89aa3 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 20 Nov 2018 18:42:49 -0500 Subject: [PATCH 0093/1984] fix more links --- .../src/language-features/macro-literal-matcher.md | 4 ++-- src/doc/unstable-book/src/language-features/plugin.md | 2 -- src/libcore/iter/iterator.rs | 6 +++--- src/libstd/lib.rs | 10 +++++----- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/macro-literal-matcher.md b/src/doc/unstable-book/src/language-features/macro-literal-matcher.md index 7e3638fd1cf..870158200de 100644 --- a/src/doc/unstable-book/src/language-features/macro-literal-matcher.md +++ b/src/doc/unstable-book/src/language-features/macro-literal-matcher.md @@ -4,7 +4,7 @@ The tracking issue for this feature is: [#35625] The RFC is: [rfc#1576]. -With this feature gate enabled, the [list of fragment specifiers][frags] gains one more entry: +With this feature gate enabled, the [list of designators] gains one more entry: * `literal`: a literal. Examples: 2, "string", 'c' @@ -12,6 +12,6 @@ A `literal` may be followed by anything, similarly to the `ident` specifier. [rfc#1576]: http://rust-lang.github.io/rfcs/1576-macros-literal-matcher.html [#35625]: https://github.com/rust-lang/rust/issues/35625 -[frags]: ../book/first-edition/macros.html#syntactic-requirements +[list of designators]: ../reference/macros-by-example.html ------------------------ diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index b408d5d0805..74bdd4dc3b5 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -137,8 +137,6 @@ of extensions. See `Registry::register_syntax_extension` and the ## Tips and tricks -Some of the [macro debugging tips](../book/first-edition/macros.html#debugging-macro-code) are applicable. - You can use `syntax::parse` to turn token trees into higher-level syntax elements like expressions: diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 2903c370df8..fd4189ef50d 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -532,7 +532,7 @@ pub trait Iterator { /// If you're doing some sort of looping for a side effect, it's considered /// more idiomatic to use [`for`] than `map()`. /// - /// [`for`]: ../../book/first-edition/loops.html#for + /// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for /// /// # Examples /// @@ -580,7 +580,7 @@ pub trait Iterator { /// cases `for_each` may also be faster than a loop, because it will use /// internal iteration on adaptors like `Chain`. /// - /// [`for`]: ../../book/first-edition/loops.html#for + /// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for /// /// # Examples /// @@ -1669,7 +1669,7 @@ pub trait Iterator { /// use a `for` loop with a list of things to build up a result. Those /// can be turned into `fold()`s: /// - /// [`for`]: ../../book/first-edition/loops.html#for + /// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for /// /// ``` /// let numbers = [1, 2, 3, 4, 5]; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index f460d109c89..eb7caa61972 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -185,7 +185,7 @@ //! [slice]: primitive.slice.html //! [`atomic`]: sync/atomic/index.html //! [`collections`]: collections/index.html -//! [`for`]: ../book/first-edition/loops.html#for +/// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for //! [`format!`]: macro.format.html //! [`fs`]: fs/index.html //! [`io`]: io/index.html @@ -200,14 +200,14 @@ //! [`sync`]: sync/index.html //! [`thread`]: thread/index.html //! [`use std::env`]: env/index.html -//! [`use`]: ../book/first-edition/crates-and-modules.html#importing-modules-with-use -//! [crate root]: ../book/first-edition/crates-and-modules.html#basic-terminology-crates-and-modules +//! [`use`]: ../book/ch07-02-modules-and-use-to-control-scope-and-privacy.html#use-to-bring-paths-into-scope +//! [crate root]: ../book/ch07-01-packages-and-crates-for-making-libraries-and-executables.html //! [crates.io]: https://crates.io -//! [deref-coercions]: ../book/second-edition/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods +//! [deref-coercions]: ../book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods //! [files]: fs/struct.File.html //! [multithreading]: thread/index.html //! [other]: #what-is-in-the-standard-library-documentation -//! [primitive types]: ../book/first-edition/primitive-types.html +//! [primitive types]: ../book/ch03-02-data-types.html #![stable(feature = "rust1", since = "1.0.0")] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", From 09e7051b7eb1d2aa1e1d34b7b09a594cba901141 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Tue, 20 Nov 2018 21:12:30 -0800 Subject: [PATCH 0094/1984] Add unstable Literal::subspan(). --- src/libproc_macro/lib.rs | 47 ++++++++++- src/test/ui-fulldeps/auxiliary/subspan.rs | 47 +++++++++++ src/test/ui-fulldeps/subspan.rs | 37 +++++++++ src/test/ui-fulldeps/subspan.stderr | 98 +++++++++++++++++++++++ 4 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 src/test/ui-fulldeps/auxiliary/subspan.rs create mode 100644 src/test/ui-fulldeps/subspan.rs create mode 100644 src/test/ui-fulldeps/subspan.stderr diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 60b6a8bac41..e9d2d97e364 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -50,6 +50,7 @@ mod diagnostic; #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub use diagnostic::{Diagnostic, Level, MultiSpan}; +use std::ops::{Bound, RangeBounds}; use std::{ascii, fmt, iter}; use std::path::PathBuf; use rustc_data_structures::sync::Lrc; @@ -59,7 +60,7 @@ use syntax::errors::DiagnosticBuilder; use syntax::parse::{self, token}; use syntax::symbol::Symbol; use syntax::tokenstream::{self, DelimSpan}; -use syntax_pos::{Pos, FileName}; +use syntax_pos::{Pos, FileName, BytePos}; /// The main type provided by this crate, representing an abstract stream of /// tokens, or, more specifically, a sequence of token trees. @@ -1168,6 +1169,50 @@ impl Literal { pub fn set_span(&mut self, span: Span) { self.span = span; } + + /// Returns a `Span` that is a subset of `self.span()` containing only the + /// source bytes in range `range`. Returns `None` if the would-be trimmed + /// span is outside the bounds of `self`. + // FIXME(SergioBenitez): check that the byte range starts and ends at a + // UTF-8 boundary of the source. otherwise, it's likely that a panic will + // occur elsewhere when the source text is printed. + // FIXME(SergioBenitez): there is no way for the user to know what + // `self.span()` actually maps to, so this method can currently only be + // called blindly. For example, `to_string()` for the character 'c' returns + // "'\u{63}'"; there is no way for the user to know whether the source text + // was 'c' or whether it was '\u{63}'. + #[unstable(feature = "proc_macro_span", issue = "54725")] + pub fn subspan>(&self, range: R) -> Option { + let inner = self.span().0; + let length = inner.hi().to_usize() - inner.lo().to_usize(); + + let start = match range.start_bound() { + Bound::Included(&lo) => lo, + Bound::Excluded(&lo) => lo + 1, + Bound::Unbounded => 0, + }; + + let end = match range.end_bound() { + Bound::Included(&hi) => hi + 1, + Bound::Excluded(&hi) => hi, + Bound::Unbounded => length, + }; + + // Bounds check the values, preventing addition overflow and OOB spans. + if start > u32::max_value() as usize + || end > u32::max_value() as usize + || (u32::max_value() - start as u32) < inner.lo().to_u32() + || (u32::max_value() - end as u32) < inner.lo().to_u32() + || start >= end + || end > length + { + return None; + } + + let new_lo = inner.lo() + BytePos::from_usize(start); + let new_hi = inner.lo() + BytePos::from_usize(end); + Some(Span(inner.with_lo(new_lo).with_hi(new_hi))) + } } /// Prints the literal as a string that should be losslessly convertible diff --git a/src/test/ui-fulldeps/auxiliary/subspan.rs b/src/test/ui-fulldeps/auxiliary/subspan.rs new file mode 100644 index 00000000000..134b04d7333 --- /dev/null +++ b/src/test/ui-fulldeps/auxiliary/subspan.rs @@ -0,0 +1,47 @@ +// Copyright 2018 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. + +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_diagnostic, proc_macro_span)] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span, Diagnostic}; + +fn parse(input: TokenStream) -> Result<(), Diagnostic> { + if let Some(TokenTree::Literal(lit)) = input.into_iter().next() { + let mut spans = vec![]; + let string = lit.to_string(); + for hi in string.matches("hi") { + let index = hi.as_ptr() as usize - string.as_ptr() as usize; + let subspan = lit.subspan(index..(index + hi.len())).unwrap(); + spans.push(subspan); + } + + if !spans.is_empty() { + Err(Span::call_site().error("found 'hi's").span_note(spans, "here")) + } else { + Ok(()) + } + } else { + Err(Span::call_site().error("invalid input: expected string literal")) + } +} + +#[proc_macro] +pub fn subspan(input: TokenStream) -> TokenStream { + if let Err(diag) = parse(input) { + diag.emit(); + } + + TokenStream::new() +} diff --git a/src/test/ui-fulldeps/subspan.rs b/src/test/ui-fulldeps/subspan.rs new file mode 100644 index 00000000000..437123ca479 --- /dev/null +++ b/src/test/ui-fulldeps/subspan.rs @@ -0,0 +1,37 @@ +// Copyright 2018 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:subspan.rs +// ignore-stage1 + +extern crate subspan; + +use subspan::subspan; + +// This one emits no error. +subspan!(""); + +// Exactly one 'hi'. +subspan!("hi"); //~ ERROR found 'hi's + +// Now two, back to back. +subspan!("hihi"); //~ ERROR found 'hi's + +// Now three, back to back. +subspan!("hihihi"); //~ ERROR found 'hi's + +// Now several, with spacing. +subspan!("why I hide? hi!"); //~ ERROR found 'hi's +subspan!("hey, hi, hidy, hidy, hi hi"); //~ ERROR found 'hi's +subspan!("this is a hi, and this is another hi"); //~ ERROR found 'hi's +subspan!("how are you this evening"); //~ ERROR found 'hi's +subspan!("this is highly eradic"); //~ ERROR found 'hi's + +fn main() { } diff --git a/src/test/ui-fulldeps/subspan.stderr b/src/test/ui-fulldeps/subspan.stderr new file mode 100644 index 00000000000..4d3928cae72 --- /dev/null +++ b/src/test/ui-fulldeps/subspan.stderr @@ -0,0 +1,98 @@ +error: found 'hi's + --> $DIR/subspan.rs:22:1 + | +LL | subspan!("hi"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:22:11 + | +LL | subspan!("hi"); //~ ERROR found 'hi's + | ^^ + +error: found 'hi's + --> $DIR/subspan.rs:25:1 + | +LL | subspan!("hihi"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:25:11 + | +LL | subspan!("hihi"); //~ ERROR found 'hi's + | ^^^^ + +error: found 'hi's + --> $DIR/subspan.rs:28:1 + | +LL | subspan!("hihihi"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:28:11 + | +LL | subspan!("hihihi"); //~ ERROR found 'hi's + | ^^^^^^ + +error: found 'hi's + --> $DIR/subspan.rs:31:1 + | +LL | subspan!("why I hide? hi!"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:31:17 + | +LL | subspan!("why I hide? hi!"); //~ ERROR found 'hi's + | ^^ ^^ + +error: found 'hi's + --> $DIR/subspan.rs:32:1 + | +LL | subspan!("hey, hi, hidy, hidy, hi hi"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:32:16 + | +LL | subspan!("hey, hi, hidy, hidy, hi hi"); //~ ERROR found 'hi's + | ^^ ^^ ^^ ^^ ^^ + +error: found 'hi's + --> $DIR/subspan.rs:33:1 + | +LL | subspan!("this is a hi, and this is another hi"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:33:12 + | +LL | subspan!("this is a hi, and this is another hi"); //~ ERROR found 'hi's + | ^^ ^^ ^^ ^^ + +error: found 'hi's + --> $DIR/subspan.rs:34:1 + | +LL | subspan!("how are you this evening"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:34:24 + | +LL | subspan!("how are you this evening"); //~ ERROR found 'hi's + | ^^ + +error: found 'hi's + --> $DIR/subspan.rs:35:1 + | +LL | subspan!("this is highly eradic"); //~ ERROR found 'hi's + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:35:12 + | +LL | subspan!("this is highly eradic"); //~ ERROR found 'hi's + | ^^ ^^ + +error: aborting due to 8 previous errors + From 9e2e57511f13569c8e9de910c04540ad1b93a321 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Mon, 19 Nov 2018 15:05:28 +0530 Subject: [PATCH 0095/1984] Add x86_64-fortanix-unknown-sgx target to the compiler --- src/librustc_target/spec/mod.rs | 2 + .../spec/x86_64_fortanix_unknown_sgx.rs | 72 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 57bbf6b0260..986607e9ca7 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -412,6 +412,8 @@ supported_targets! { ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf), ("aarch64-unknown-none", aarch64_unknown_none), + + ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx), } /// Everything `rustc` knows about how to compile for a specific target. diff --git a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs new file mode 100644 index 00000000000..07383b3d648 --- /dev/null +++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs @@ -0,0 +1,72 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::iter; + +use super::{LinkerFlavor, Target, TargetOptions, PanicStrategy}; + +pub fn target() -> Result { + const PRE_LINK_ARGS: &[&str] = &[ + "-Wl,--as-needed", + "-Wl,-z,noexecstack", + "-m64", + "-fuse-ld=gold", + "-nostdlib", + "-shared", + "-Wl,-e,sgx_entry", + "-Wl,-Bstatic", + "-Wl,--gc-sections", + "-Wl,-z,text", + "-Wl,-z,norelro", + "-Wl,--rosegment", + "-Wl,--no-undefined", + "-Wl,--error-unresolved-symbols", + "-Wl,--no-undefined-version", + "-Wl,-Bsymbolic", + "-Wl,--export-dynamic", + ]; + const EXPORT_SYMBOLS: &[&str] = &[ + "sgx_entry", + "HEAP_BASE", + "HEAP_SIZE", + "RELA", + "RELACOUNT", + "ENCLAVE_SIZE", + "CFGDATA_BASE", + "DEBUG", + ]; + let opts = TargetOptions { + dynamic_linking: false, + executables: true, + linker_is_gnu: true, + max_atomic_width: Some(64), + panic_strategy: PanicStrategy::Abort, + cpu: "x86-64".into(), + position_independent_executables: true, + pre_link_args: iter::once( + (LinkerFlavor::Gcc, PRE_LINK_ARGS.iter().cloned().map(String::from).collect()) + ).collect(), + override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(String::from).collect()), + ..Default::default() + }; + Ok(Target { + llvm_target: "x86_64-unknown-linux-gnu".into(), + target_endian: "little".into(), + target_pointer_width: "64".into(), + target_c_int_width: "32".into(), + target_os: "unknown".into(), + target_env: "sgx".into(), + target_vendor: "fortanix".into(), + data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".into(), + arch: "x86_64".into(), + linker_flavor: LinkerFlavor::Gcc, + options: opts, + }) +} From 700c83bc05ebeddbe3d3a10c2e309826d563b12b Mon Sep 17 00:00:00 2001 From: Bastian Gruber Date: Sun, 24 Jun 2018 09:38:56 +0200 Subject: [PATCH 0096/1984] Document `From` implementations --- src/libstd/path.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index a153456370c..ab37bb75209 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1397,6 +1397,8 @@ impl<'a> From<&'a Path> for Box { #[stable(feature = "path_buf_from_box", since = "1.18.0")] impl From> for PathBuf { + /// Converts a `Box` into a `PathBuf`. + /// This conversion does not allocate memory fn from(boxed: Box) -> PathBuf { boxed.into_path_buf() } @@ -1404,6 +1406,8 @@ impl From> for PathBuf { #[stable(feature = "box_from_path_buf", since = "1.20.0")] impl From for Box { + /// Converts a `PathBuf` into a `Box`. + /// This conversion does not allocate memory fn from(p: PathBuf) -> Box { p.into_boxed_path() } @@ -1426,6 +1430,9 @@ impl<'a, T: ?Sized + AsRef> From<&'a T> for PathBuf { #[stable(feature = "rust1", since = "1.0.0")] impl From for PathBuf { + /// Converts a `OsString` into a `PathBuf`. + /// This conversion copies the data. + /// This conversion does allocate memory. fn from(s: OsString) -> PathBuf { PathBuf { inner: s } } @@ -1433,6 +1440,9 @@ impl From for PathBuf { #[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")] impl From for OsString { + /// Converts a `PathBuf` into a `OsString`. + /// This conversion copies the data. + /// This conversion does allocate memory. fn from(path_buf : PathBuf) -> OsString { path_buf.inner } @@ -1440,6 +1450,8 @@ impl From for OsString { #[stable(feature = "rust1", since = "1.0.0")] impl From for PathBuf { + /// Converts a `String` into a `PathBuf`. + /// This conversion does not allocate memory fn from(s: String) -> PathBuf { PathBuf::from(OsString::from(s)) } @@ -1536,6 +1548,10 @@ impl<'a> From> for PathBuf { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Arc { + /// Converts a `PathBuf` into a `Arc`. + /// This conversion happens in place. + /// This conversion does not allocate memory. + /// This function is unsafe. Data can't be moved from this reference. #[inline] fn from(s: PathBuf) -> Arc { let arc: Arc = Arc::from(s.into_os_string()); @@ -1545,6 +1561,10 @@ impl From for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl<'a> From<&'a Path> for Arc { + /// Converts a `PathBuf` into a `Arc`. + /// This conversion happens in place. + /// This conversion does not allocate memory. + /// This function is unsafe. Data can't be moved from this reference. #[inline] fn from(s: &Path) -> Arc { let arc: Arc = Arc::from(s.as_os_str()); @@ -1554,6 +1574,10 @@ impl<'a> From<&'a Path> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { + /// Converts a `PathBuf` into a `Rc`. + /// This conversion happens in place. + /// This conversion does not allocate memory. + /// This function is unsafe. Data can't be moved from this reference. #[inline] fn from(s: PathBuf) -> Rc { let rc: Rc = Rc::from(s.into_os_string()); From 072bca3ff5a3907a71c22fba041825cfa3eb321e Mon Sep 17 00:00:00 2001 From: Bastian Gruber Date: Mon, 25 Jun 2018 14:24:39 +0200 Subject: [PATCH 0097/1984] Remove 'unsafe' comments --- src/libstd/path.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index ab37bb75209..9145eeb6063 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1551,7 +1551,6 @@ impl From for Arc { /// Converts a `PathBuf` into a `Arc`. /// This conversion happens in place. /// This conversion does not allocate memory. - /// This function is unsafe. Data can't be moved from this reference. #[inline] fn from(s: PathBuf) -> Arc { let arc: Arc = Arc::from(s.into_os_string()); @@ -1564,7 +1563,6 @@ impl<'a> From<&'a Path> for Arc { /// Converts a `PathBuf` into a `Arc`. /// This conversion happens in place. /// This conversion does not allocate memory. - /// This function is unsafe. Data can't be moved from this reference. #[inline] fn from(s: &Path) -> Arc { let arc: Arc = Arc::from(s.as_os_str()); @@ -1577,7 +1575,6 @@ impl From for Rc { /// Converts a `PathBuf` into a `Rc`. /// This conversion happens in place. /// This conversion does not allocate memory. - /// This function is unsafe. Data can't be moved from this reference. #[inline] fn from(s: PathBuf) -> Rc { let rc: Rc = Rc::from(s.into_os_string()); From 88a708dd6a5bb14f3a19ae98238ddf2d03cb93d3 Mon Sep 17 00:00:00 2001 From: Bastian Gruber Date: Mon, 25 Jun 2018 21:29:22 +0200 Subject: [PATCH 0098/1984] Update comments --- src/libstd/path.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 9145eeb6063..e631bb90f57 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1431,8 +1431,7 @@ impl<'a, T: ?Sized + AsRef> From<&'a T> for PathBuf { #[stable(feature = "rust1", since = "1.0.0")] impl From for PathBuf { /// Converts a `OsString` into a `PathBuf`. - /// This conversion copies the data. - /// This conversion does allocate memory. + /// This conversion does not allocate memory fn from(s: OsString) -> PathBuf { PathBuf { inner: s } } @@ -1441,8 +1440,7 @@ impl From for PathBuf { #[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")] impl From for OsString { /// Converts a `PathBuf` into a `OsString`. - /// This conversion copies the data. - /// This conversion does allocate memory. + /// This conversion does not allocate memory fn from(path_buf : PathBuf) -> OsString { path_buf.inner } From 5c747eb32654401b9b6fe053c3f51399a6454f8c Mon Sep 17 00:00:00 2001 From: Bastian Gruber Date: Thu, 26 Jul 2018 10:59:46 +0200 Subject: [PATCH 0099/1984] Update style of comments --- src/libstd/path.rs | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index e631bb90f57..9f6fcad2422 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1397,7 +1397,8 @@ impl<'a> From<&'a Path> for Box { #[stable(feature = "path_buf_from_box", since = "1.18.0")] impl From> for PathBuf { - /// Converts a `Box` into a `PathBuf`. + /// Converts a `Box` into a `PathBuf` + /// /// This conversion does not allocate memory fn from(boxed: Box) -> PathBuf { boxed.into_path_buf() @@ -1406,7 +1407,8 @@ impl From> for PathBuf { #[stable(feature = "box_from_path_buf", since = "1.20.0")] impl From for Box { - /// Converts a `PathBuf` into a `Box`. + /// Converts a `PathBuf` into a `Box` + /// /// This conversion does not allocate memory fn from(p: PathBuf) -> Box { p.into_boxed_path() @@ -1430,7 +1432,8 @@ impl<'a, T: ?Sized + AsRef> From<&'a T> for PathBuf { #[stable(feature = "rust1", since = "1.0.0")] impl From for PathBuf { - /// Converts a `OsString` into a `PathBuf`. + /// Converts a `OsString` into a `PathBuf` + /// /// This conversion does not allocate memory fn from(s: OsString) -> PathBuf { PathBuf { inner: s } @@ -1439,7 +1442,8 @@ impl From for PathBuf { #[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")] impl From for OsString { - /// Converts a `PathBuf` into a `OsString`. + /// Converts a `PathBuf` into a `OsString` + /// /// This conversion does not allocate memory fn from(path_buf : PathBuf) -> OsString { path_buf.inner @@ -1448,7 +1452,8 @@ impl From for OsString { #[stable(feature = "rust1", since = "1.0.0")] impl From for PathBuf { - /// Converts a `String` into a `PathBuf`. + /// Converts a `String` into a `PathBuf` + /// /// This conversion does not allocate memory fn from(s: String) -> PathBuf { PathBuf::from(OsString::from(s)) @@ -1546,9 +1551,11 @@ impl<'a> From> for PathBuf { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Arc { - /// Converts a `PathBuf` into a `Arc`. - /// This conversion happens in place. - /// This conversion does not allocate memory. + /// Converts a `PathBuf` into a `Arc` + /// + /// This conversion happens in place + /// + /// This conversion does not allocate memory #[inline] fn from(s: PathBuf) -> Arc { let arc: Arc = Arc::from(s.into_os_string()); @@ -1558,9 +1565,12 @@ impl From for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl<'a> From<&'a Path> for Arc { - /// Converts a `PathBuf` into a `Arc`. - /// This conversion happens in place. - /// This conversion does not allocate memory. + /// Converts a `PathBuf` into a `Arc` + /// + /// This conversion happens in place + /// + /// This conversion does not allocate memory + /// #[inline] fn from(s: &Path) -> Arc { let arc: Arc = Arc::from(s.as_os_str()); @@ -1570,9 +1580,11 @@ impl<'a> From<&'a Path> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { - /// Converts a `PathBuf` into a `Rc`. - /// This conversion happens in place. - /// This conversion does not allocate memory. + /// Converts a `PathBuf` into a `Rc` + /// + /// This conversion happens in place + /// + /// This conversion does not allocate memory #[inline] fn from(s: PathBuf) -> Rc { let rc: Rc = Rc::from(s.into_os_string()); From 464c9da9c229111298d413882735ea707a30e077 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 21 Nov 2018 10:07:33 +0100 Subject: [PATCH 0100/1984] serialize: preallocate VecDeque in Decodable::decode --- src/libserialize/collection_impls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index 3e028d755c6..cbd642dd6ad 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -86,7 +86,7 @@ impl Encodable for VecDeque { impl Decodable for VecDeque { fn decode(d: &mut D) -> Result, D::Error> { d.read_seq(|d, len| { - let mut deque: VecDeque = VecDeque::new(); + let mut deque: VecDeque = VecDeque::with_capacity(len); for i in 0..len { deque.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))?); } From 591607d237665857880e16899788517b9b82d414 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 21 Nov 2018 10:17:54 +0100 Subject: [PATCH 0101/1984] String: add a FIXME to from_utf16 --- src/liballoc/string.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 8d009101ce7..0b25d911a29 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -618,6 +618,8 @@ impl String { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf16(v: &[u16]) -> Result { + // This isn't done via collect::>() for performance reasons. + // FIXME: the function can be simplified again when #48994 is closed. let mut ret = String::with_capacity(v.len()); for c in decode_utf16(v.iter().cloned()) { if let Ok(c) = c { From 301ce8b2aa6156ae8dc535ca234e95b04e7c4e4b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 21 Nov 2018 10:37:18 +0100 Subject: [PATCH 0102/1984] Properly assign to aggregate fields --- src/librustc_mir/transform/qualify_consts.rs | 7 ++++++- src/test/ui/consts/partial_qualif.rs | 11 +++++++++++ src/test/ui/consts/partial_qualif.stderr | 9 +++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/consts/partial_qualif.rs create mode 100644 src/test/ui/consts/partial_qualif.stderr diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index f8ecd963457..51e590fe292 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -267,7 +267,12 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { } }; debug!("store to var {:?}", index); - self.local_qualif[index] = Some(self.qualif); + match &mut self.local_qualif[index] { + // update + Some(ref mut qualif) => *qualif = *qualif | self.qualif, + // or insert + qualif @ None => *qualif = Some(self.qualif), + } return; } diff --git a/src/test/ui/consts/partial_qualif.rs b/src/test/ui/consts/partial_qualif.rs new file mode 100644 index 00000000000..bb3fc92d4fb --- /dev/null +++ b/src/test/ui/consts/partial_qualif.rs @@ -0,0 +1,11 @@ +#![feature(const_let)] + +use std::cell::Cell; + +const FOO: &(Cell, bool) = { + let mut a = (Cell::new(0), false); + a.1 = true; // resets `qualif(a)` to `qualif(true)` + &{a} //~ ERROR cannot borrow a constant which may contain interior mutability +}; + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/consts/partial_qualif.stderr b/src/test/ui/consts/partial_qualif.stderr new file mode 100644 index 00000000000..d695f64e2c3 --- /dev/null +++ b/src/test/ui/consts/partial_qualif.stderr @@ -0,0 +1,9 @@ +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/partial_qualif.rs:8:5 + | +LL | &{a} //~ ERROR cannot borrow a constant which may contain interior mutability + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0492`. From 3c290a5326755d5f978caf66cfd61b05652169d5 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 21 Nov 2018 10:42:40 +0100 Subject: [PATCH 0103/1984] Ensure assignments don't allow skipping projection checks --- src/librustc_mir/transform/qualify_consts.rs | 11 ++++++++++- src/test/ui/consts/projection_qualif.rs | 14 ++++++++++++++ src/test/ui/consts/projection_qualif.stderr | 18 ++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/consts/projection_qualif.rs create mode 100644 src/test/ui/consts/projection_qualif.stderr diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 51e590fe292..571fe998970 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -252,7 +252,16 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { // projections are transparent for assignments // we qualify the entire destination at once, even if just a field would have // stricter qualification - Place::Projection(proj) => dest = &proj.base, + Place::Projection(proj) => { + // Catch more errors in the destination. `visit_place` also checks various + // projection rules like union field access and raw pointer deref + self.visit_place( + dest, + PlaceContext::MutatingUse(MutatingUseContext::Store), + location + ); + dest = &proj.base; + }, Place::Promoted(..) => bug!("promoteds don't exist yet during promotion"), Place::Static(..) => { // Catch more errors in the destination. `visit_place` also checks that we diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/projection_qualif.rs new file mode 100644 index 00000000000..4806fecee43 --- /dev/null +++ b/src/test/ui/consts/projection_qualif.rs @@ -0,0 +1,14 @@ +#![feature(const_let)] + +use std::cell::Cell; + +const FOO: &u32 = { + let mut a = 42; + { + let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values + unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants + } + &{a} +}; + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/consts/projection_qualif.stderr b/src/test/ui/consts/projection_qualif.stderr new file mode 100644 index 00000000000..d5252f199be --- /dev/null +++ b/src/test/ui/consts/projection_qualif.stderr @@ -0,0 +1,18 @@ +error[E0017]: references in constants may only refer to immutable values + --> $DIR/projection_qualif.rs:8:27 + | +LL | let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values + | ^^^^^^ constants require immutable values + +error[E0658]: dereferencing raw pointers in constants is unstable (see issue #51911) + --> $DIR/projection_qualif.rs:9:18 + | +LL | unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants + | ^^^^^^ + | + = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable + +error: aborting due to 2 previous errors + +Some errors occurred: E0017, E0658. +For more information about an error, try `rustc --explain E0017`. From 42a3f730c75c4e4b62eb58d4e09a8ec833e13804 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 21 Nov 2018 11:13:49 +0100 Subject: [PATCH 0104/1984] Tidy --- src/test/ui/consts/partial_qualif.rs | 2 +- src/test/ui/consts/projection_qualif.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/consts/partial_qualif.rs b/src/test/ui/consts/partial_qualif.rs index bb3fc92d4fb..7cf9ee1d94b 100644 --- a/src/test/ui/consts/partial_qualif.rs +++ b/src/test/ui/consts/partial_qualif.rs @@ -8,4 +8,4 @@ const FOO: &(Cell, bool) = { &{a} //~ ERROR cannot borrow a constant which may contain interior mutability }; -fn main() {} \ No newline at end of file +fn main() {} diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/projection_qualif.rs index 4806fecee43..34e8eaba9f2 100644 --- a/src/test/ui/consts/projection_qualif.rs +++ b/src/test/ui/consts/projection_qualif.rs @@ -11,4 +11,4 @@ const FOO: &u32 = { &{a} }; -fn main() {} \ No newline at end of file +fn main() {} From 1ed91951c3012e9aabb403d28b902c56cc143907 Mon Sep 17 00:00:00 2001 From: antoine-de Date: Wed, 21 Nov 2018 11:17:48 +0100 Subject: [PATCH 0105/1984] fix small doc mistake The std::io::read main documentation can lead to error because the buffer is prefilled with 10 zeros that will pad the response. Using an empty vector is better. The `read_to_end` documentation is already correct though. This is my first rust PR, don't hesitate to tell me if I did something wrong. --- src/libstd/io/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index e263db24fc2..076524e624a 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -431,7 +431,7 @@ fn read_to_end_with_reservation(r: &mut R, /// // read up to 10 bytes /// f.read(&mut buffer)?; /// -/// let mut buffer = vec![0; 10]; +/// let mut buffer = Vec::new(); /// // read the whole file /// f.read_to_end(&mut buffer)?; /// From e05b61ccd8fcb4bb4fd12085fc13522b940e7618 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 21 Nov 2018 11:47:16 +0100 Subject: [PATCH 0106/1984] Fix a comment --- src/test/ui/consts/partial_qualif.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/consts/partial_qualif.rs b/src/test/ui/consts/partial_qualif.rs index 7cf9ee1d94b..4ce41f80f82 100644 --- a/src/test/ui/consts/partial_qualif.rs +++ b/src/test/ui/consts/partial_qualif.rs @@ -4,7 +4,7 @@ use std::cell::Cell; const FOO: &(Cell, bool) = { let mut a = (Cell::new(0), false); - a.1 = true; // resets `qualif(a)` to `qualif(true)` + a.1 = true; // sets `qualif(a)` to `qualif(a) | qualif(true)` &{a} //~ ERROR cannot borrow a constant which may contain interior mutability }; From 22aebd57c8ed5344260059abebbb938683ab4d91 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 21 Nov 2018 11:47:44 +0100 Subject: [PATCH 0107/1984] Add regression test for overwriting qualifs by assignment --- src/test/ui/consts/qualif_overwrite.rs | 13 +++++++++++++ src/test/ui/consts/qualif_overwrite.stderr | 9 +++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/test/ui/consts/qualif_overwrite.rs create mode 100644 src/test/ui/consts/qualif_overwrite.stderr diff --git a/src/test/ui/consts/qualif_overwrite.rs b/src/test/ui/consts/qualif_overwrite.rs new file mode 100644 index 00000000000..65e182945bf --- /dev/null +++ b/src/test/ui/consts/qualif_overwrite.rs @@ -0,0 +1,13 @@ +// compile-pass + +#![feature(const_let)] + +use std::cell::Cell; + +const FOO: &Option> = { + let mut a = Some(Cell::new(0)); + a = None; // resets `qualif(a)` to `qualif(None)` + &{a} +}; + +fn main() {} diff --git a/src/test/ui/consts/qualif_overwrite.stderr b/src/test/ui/consts/qualif_overwrite.stderr new file mode 100644 index 00000000000..b24c0fa70f0 --- /dev/null +++ b/src/test/ui/consts/qualif_overwrite.stderr @@ -0,0 +1,9 @@ +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/qualif_overwrite.rs:8:5 + | +LL | &{a} //~ ERROR cannot borrow a constant which may contain interior mutability + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0492`. From e538a4a7debaff6627c11f4a5d2cb29beea0b336 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Tue, 13 Nov 2018 13:54:51 +0100 Subject: [PATCH 0108/1984] core/benches/num: Add `from_str/from_str_radix()` benchmarks --- src/libcore/benches/num/mod.rs | 105 +++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/src/libcore/benches/num/mod.rs b/src/libcore/benches/num/mod.rs index 55f0bdb57ec..b57e167b05d 100644 --- a/src/libcore/benches/num/mod.rs +++ b/src/libcore/benches/num/mod.rs @@ -10,3 +10,108 @@ mod flt2dec; mod dec2flt; + +use test::Bencher; +use std::str::FromStr; + +const ASCII_NUMBERS: [&str; 19] = [ + "0", + "1", + "2", + "43", + "765", + "76567", + "987245987", + "-4aa32", + "1786235", + "8723095", + "f##5s", + "83638730", + "-2345", + "562aa43", + "-1", + "-0", + "abc", + "xyz", + "c0ffee", +]; + +macro_rules! from_str_bench { + ($mac:ident, $t:ty) => ( + #[bench] + fn $mac(b: &mut Bencher) { + b.iter(|| { + ASCII_NUMBERS + .iter() + .cycle() + .take(5_000) + .filter_map(|s| <($t)>::from_str(s).ok()) + .max() + }) + } + ) +} + +macro_rules! from_str_radix_bench { + ($mac:ident, $t:ty, $radix:expr) => ( + #[bench] + fn $mac(b: &mut Bencher) { + b.iter(|| { + ASCII_NUMBERS + .iter() + .cycle() + .take(5_000) + .filter_map(|s| <($t)>::from_str_radix(s, $radix).ok()) + .max() + }) + } + ) +} + +from_str_bench!(bench_u8_from_str, u8); +from_str_radix_bench!(bench_u8_from_str_radix_2, u8, 2); +from_str_radix_bench!(bench_u8_from_str_radix_10, u8, 10); +from_str_radix_bench!(bench_u8_from_str_radix_16, u8, 16); +from_str_radix_bench!(bench_u8_from_str_radix_36, u8, 36); + +from_str_bench!(bench_u16_from_str, u16); +from_str_radix_bench!(bench_u16_from_str_radix_2, u16, 2); +from_str_radix_bench!(bench_u16_from_str_radix_10, u16, 10); +from_str_radix_bench!(bench_u16_from_str_radix_16, u16, 16); +from_str_radix_bench!(bench_u16_from_str_radix_36, u16, 36); + +from_str_bench!(bench_u32_from_str, u32); +from_str_radix_bench!(bench_u32_from_str_radix_2, u32, 2); +from_str_radix_bench!(bench_u32_from_str_radix_10, u32, 10); +from_str_radix_bench!(bench_u32_from_str_radix_16, u32, 16); +from_str_radix_bench!(bench_u32_from_str_radix_36, u32, 36); + +from_str_bench!(bench_u64_from_str, u64); +from_str_radix_bench!(bench_u64_from_str_radix_2, u64, 2); +from_str_radix_bench!(bench_u64_from_str_radix_10, u64, 10); +from_str_radix_bench!(bench_u64_from_str_radix_16, u64, 16); +from_str_radix_bench!(bench_u64_from_str_radix_36, u64, 36); + +from_str_bench!(bench_i8_from_str, i8); +from_str_radix_bench!(bench_i8_from_str_radix_2, i8, 2); +from_str_radix_bench!(bench_i8_from_str_radix_10, i8, 10); +from_str_radix_bench!(bench_i8_from_str_radix_16, i8, 16); +from_str_radix_bench!(bench_i8_from_str_radix_36, i8, 36); + +from_str_bench!(bench_i16_from_str, i16); +from_str_radix_bench!(bench_i16_from_str_radix_2, i16, 2); +from_str_radix_bench!(bench_i16_from_str_radix_10, i16, 10); +from_str_radix_bench!(bench_i16_from_str_radix_16, i16, 16); +from_str_radix_bench!(bench_i16_from_str_radix_36, i16, 36); + +from_str_bench!(bench_i32_from_str, i32); +from_str_radix_bench!(bench_i32_from_str_radix_2, i32, 2); +from_str_radix_bench!(bench_i32_from_str_radix_10, i32, 10); +from_str_radix_bench!(bench_i32_from_str_radix_16, i32, 16); +from_str_radix_bench!(bench_i32_from_str_radix_36, i32, 36); + +from_str_bench!(bench_i64_from_str, i64); +from_str_radix_bench!(bench_i64_from_str_radix_2, i64, 2); +from_str_radix_bench!(bench_i64_from_str_radix_10, i64, 10); +from_str_radix_bench!(bench_i64_from_str_radix_16, i64, 16); +from_str_radix_bench!(bench_i64_from_str_radix_36, i64, 36); From 6db8c6c6d9fd1f8226b3afd9e18c6fb3cd2f1176 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 21 Nov 2018 11:58:28 +0100 Subject: [PATCH 0109/1984] Explain why we do not overwrite qualification of locals --- src/librustc_mir/transform/qualify_consts.rs | 7 +++++-- src/test/ui/consts/qualif_overwrite.rs | 10 ++++++---- src/test/ui/consts/qualif_overwrite.stderr | 2 +- src/test/ui/consts/qualif_overwrite_2.rs | 13 +++++++++++++ src/test/ui/consts/qualif_overwrite_2.stderr | 9 +++++++++ 5 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/consts/qualif_overwrite_2.rs create mode 100644 src/test/ui/consts/qualif_overwrite_2.stderr diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 571fe998970..399c6dbcb7c 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -277,9 +277,12 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { }; debug!("store to var {:?}", index); match &mut self.local_qualif[index] { - // update + // this is overly restrictive, because even full assignments do not clear the qualif + // While we could special case full assignments, this would be inconsistent with + // aggregates where we overwrite all fields via assignments, which would not get + // that feature. Some(ref mut qualif) => *qualif = *qualif | self.qualif, - // or insert + // insert new qualification qualif @ None => *qualif = Some(self.qualif), } return; diff --git a/src/test/ui/consts/qualif_overwrite.rs b/src/test/ui/consts/qualif_overwrite.rs index 65e182945bf..806a74ee453 100644 --- a/src/test/ui/consts/qualif_overwrite.rs +++ b/src/test/ui/consts/qualif_overwrite.rs @@ -1,13 +1,15 @@ -// compile-pass - #![feature(const_let)] use std::cell::Cell; +// this is overly conservative. The reset to `None` should clear `a` of all qualifications +// while we could fix this, it would be inconsistent with `qualif_overwrite_2.rs`. +// We can fix this properly in the future by allowing constants that do not depend on generics +// to be checked by an analysis on the final value instead of looking at the body. const FOO: &Option> = { let mut a = Some(Cell::new(0)); - a = None; // resets `qualif(a)` to `qualif(None)` - &{a} + a = None; // sets `qualif(a)` to `qualif(a) | qualif(None)` + &{a} //~ ERROR cannot borrow a constant which may contain interior mutability }; fn main() {} diff --git a/src/test/ui/consts/qualif_overwrite.stderr b/src/test/ui/consts/qualif_overwrite.stderr index b24c0fa70f0..4fac64bf806 100644 --- a/src/test/ui/consts/qualif_overwrite.stderr +++ b/src/test/ui/consts/qualif_overwrite.stderr @@ -1,5 +1,5 @@ error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead - --> $DIR/qualif_overwrite.rs:8:5 + --> $DIR/qualif_overwrite.rs:12:5 | LL | &{a} //~ ERROR cannot borrow a constant which may contain interior mutability | ^^^^ diff --git a/src/test/ui/consts/qualif_overwrite_2.rs b/src/test/ui/consts/qualif_overwrite_2.rs new file mode 100644 index 00000000000..29557a3da47 --- /dev/null +++ b/src/test/ui/consts/qualif_overwrite_2.rs @@ -0,0 +1,13 @@ +#![feature(const_let)] + +use std::cell::Cell; + +// const qualification is not smart enough to know about fields and always assumes that there might +// be other fields that caused the qualification +const FOO: &Option> = { + let mut a = (Some(Cell::new(0)),); + a.0 = None; // sets `qualif(a)` to `qualif(a) | qualif(None)` + &{a.0} //~ ERROR cannot borrow a constant which may contain interior mutability +}; + +fn main() {} diff --git a/src/test/ui/consts/qualif_overwrite_2.stderr b/src/test/ui/consts/qualif_overwrite_2.stderr new file mode 100644 index 00000000000..181b728c7b7 --- /dev/null +++ b/src/test/ui/consts/qualif_overwrite_2.stderr @@ -0,0 +1,9 @@ +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/qualif_overwrite_2.rs:10:5 + | +LL | &{a.0} //~ ERROR cannot borrow a constant which may contain interior mutability + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0492`. From 83388e84c25f86563d82514d7bf71cfd474e008a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?= =?UTF-8?q?e=CC=B6r=20Scherer?= Date: Wed, 21 Nov 2018 12:26:40 +0100 Subject: [PATCH 0110/1984] Update an outdated comment in mir building --- src/librustc_mir/build/expr/as_temp.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index 8f50a1e9a21..19bfb35ed62 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -85,9 +85,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { unpack!(block = this.into(&Place::Local(temp), block, expr)); - // In constants, temp_lifetime is None. We should not need to drop - // anything because no values with a destructor can be created in - // a constant at this time, even if the type may need dropping. + // In constants, temp_lifetime is None. We do not drop anything because + // values with a destructor will simply be leaked in constants. if let Some(temp_lifetime) = temp_lifetime { this.schedule_drop_storage_and_value( expr_span, From 5a2a251b9cb0358851bb9d8d8870163f43c081dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?= =?UTF-8?q?e=CC=B6r=20Scherer?= Date: Wed, 21 Nov 2018 12:40:53 +0100 Subject: [PATCH 0111/1984] Update as_temp.rs --- src/librustc_mir/build/expr/as_temp.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index 19bfb35ed62..f060eefe520 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -85,8 +85,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { unpack!(block = this.into(&Place::Local(temp), block, expr)); - // In constants, temp_lifetime is None. We do not drop anything because - // values with a destructor will simply be leaked in constants. + // In constants, temp_lifetime is None for temporaries that live for the + // entire constant. Thus we do not drop these temporaries and simply leak them. + // Anything with a shorter lifetime (e.g the `&foo()` in `bar(&foo())` or anything + // within a block will keep the regular drops just like runtime code. if let Some(temp_lifetime) = temp_lifetime { this.schedule_drop_storage_and_value( expr_span, From d7b3f5c6aeedf07c6a0ea4d5a79a106642488e0d Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 20 Nov 2018 19:49:47 -0500 Subject: [PATCH 0112/1984] update various stdlib docs --- src/liballoc/rc.rs | 5 ++--- src/liballoc/sync.rs | 5 ++--- src/libcore/char/convert.rs | 6 ++---- src/libcore/mem.rs | 15 +++++---------- src/libcore/ptr.rs | 2 +- src/libcore/raw.rs | 6 +----- src/libstd/lib.rs | 4 ++-- src/libstd/macros.rs | 11 +++++------ src/libstd/primitive_docs.rs | 5 ++--- 9 files changed, 22 insertions(+), 37 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index bb52d7990ff..705345ce963 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -43,8 +43,8 @@ //! //! `Rc` automatically dereferences to `T` (via the [`Deref`] trait), //! so you can call `T`'s methods on a value of type [`Rc`][`Rc`]. To avoid name -//! clashes with `T`'s methods, the methods of [`Rc`][`Rc`] itself are [associated -//! functions][assoc], called using function-like syntax: +//! clashes with `T`'s methods, the methods of [`Rc`][`Rc`] itself are associated +//! functions, called using function-like syntax: //! //! ``` //! use std::rc::Rc; @@ -234,7 +234,6 @@ //! [downgrade]: struct.Rc.html#method.downgrade //! [upgrade]: struct.Weak.html#method.upgrade //! [`None`]: ../../std/option/enum.Option.html#variant.None -//! [assoc]: ../../book/first-edition/method-syntax.html#associated-functions //! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index b63b3684964..4f4031e3c4e 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -120,8 +120,8 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// /// `Arc` automatically dereferences to `T` (via the [`Deref`][deref] trait), /// so you can call `T`'s methods on a value of type `Arc`. To avoid name -/// clashes with `T`'s methods, the methods of `Arc` itself are [associated -/// functions][assoc], called using function-like syntax: +/// clashes with `T`'s methods, the methods of `Arc` itself are associated +/// functions, called using function-like syntax: /// /// ``` /// use std::sync::Arc; @@ -146,7 +146,6 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// [downgrade]: struct.Arc.html#method.downgrade /// [upgrade]: struct.Weak.html#method.upgrade /// [`None`]: ../../std/option/enum.Option.html#variant.None -/// [assoc]: ../../book/first-edition/method-syntax.html#associated-functions /// [`RefCell`]: ../../std/cell/struct.RefCell.html /// [`std::sync`]: ../../std/sync/index.html /// [`Arc::clone(&from)`]: #method.clone diff --git a/src/libcore/char/convert.rs b/src/libcore/char/convert.rs index e9ccdd0ea3c..160728f923d 100644 --- a/src/libcore/char/convert.rs +++ b/src/libcore/char/convert.rs @@ -19,7 +19,7 @@ use super::MAX; /// Converts a `u32` to a `char`. /// /// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with -/// [`as`]: +/// `as`: /// /// ``` /// let c = '💯'; @@ -34,7 +34,6 @@ use super::MAX; /// /// [`char`]: ../../std/primitive.char.html /// [`u32`]: ../../std/primitive.u32.html -/// [`as`]: ../../book/first-edition/casting-between-types.html#as /// /// For an unsafe version of this function which ignores these checks, see /// [`from_u32_unchecked`]. @@ -71,7 +70,7 @@ pub fn from_u32(i: u32) -> Option { /// Converts a `u32` to a `char`, ignoring validity. /// /// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with -/// [`as`]: +/// `as`: /// /// ``` /// let c = '💯'; @@ -86,7 +85,6 @@ pub fn from_u32(i: u32) -> Option { /// /// [`char`]: ../../std/primitive.char.html /// [`u32`]: ../../std/primitive.u32.html -/// [`as`]: ../../book/first-edition/casting-between-types.html#as /// /// # Safety /// diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index d8eec2bd9a6..6b2d878b3e7 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -132,7 +132,6 @@ pub use intrinsics::transmute; /// [uninit]: fn.uninitialized.html /// [clone]: ../clone/trait.Clone.html /// [swap]: fn.swap.html -/// [FFI]: ../../book/first-edition/ffi.html /// [box]: ../../std/boxed/struct.Box.html /// [leak]: ../../std/boxed/struct.Box.html#method.leak /// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw @@ -479,7 +478,7 @@ pub const fn needs_drop() -> bool { /// /// This has the same effect as allocating space with /// [`mem::uninitialized`][uninit] and then zeroing it out. It is useful for -/// [FFI] sometimes, but should generally be avoided. +/// FFI sometimes, but should generally be avoided. /// /// There is no guarantee that an all-zero byte-pattern represents a valid value of /// some type `T`. If `T` has a destructor and the value is destroyed (due to @@ -490,7 +489,6 @@ pub const fn needs_drop() -> bool { /// many of the same caveats. /// /// [uninit]: fn.uninitialized.html -/// [FFI]: ../../book/first-edition/ffi.html /// [ub]: ../../reference/behavior-considered-undefined.html /// /// # Examples @@ -514,11 +512,9 @@ pub unsafe fn zeroed() -> T { /// **This is incredibly dangerous and should not be done lightly. Deeply /// consider initializing your memory with a default value instead.** /// -/// This is useful for [FFI] functions and initializing arrays sometimes, +/// This is useful for FFI functions and initializing arrays sometimes, /// but should generally be avoided. /// -/// [FFI]: ../../book/first-edition/ffi.html -/// /// # Undefined behavior /// /// It is [undefined behavior][ub] to read uninitialized memory, even just an @@ -689,10 +685,9 @@ pub fn replace(dest: &mut T, mut src: T) -> T { /// While this does call the argument's implementation of [`Drop`][drop], /// it will not release any borrows, as borrows are based on lexical scope. /// -/// This effectively does nothing for -/// [types which implement `Copy`](../../book/first-edition/ownership.html#copy-types), -/// e.g. integers. Such values are copied and _then_ moved into the function, -/// so the value persists after this function call. +/// This effectively does nothing for types which implement `Copy`, e.g. +/// integers. Such values are copied and _then_ moved into the function, so the +/// value persists after this function call. /// /// This function is not magic; it is literally defined as /// diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index a7bfc3f5124..e9cf11424ca 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -58,7 +58,7 @@ //! [`NonNull::dangling`] in such cases. //! //! [aliasing]: ../../nomicon/aliasing.html -//! [book]: ../../book/second-edition/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer +//! [book]: ../../book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer //! [ub]: ../../reference/behavior-considered-undefined.html //! [null]: ./fn.null.html //! [zst]: ../../nomicon/exotic-sizes.html#zero-sized-types-zsts diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index a95f05227fb..495b9afe860 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -21,11 +21,7 @@ /// The representation of a trait object like `&SomeTrait`. /// /// This struct has the same layout as types like `&SomeTrait` and -/// `Box`. The [Trait Objects chapter of the -/// Book][moreinfo] contains more details about the precise nature of -/// these internals. -/// -/// [moreinfo]: ../../book/first-edition/trait-objects.html#representation +/// `Box`. /// /// `TraitObject` is guaranteed to match layouts, but it is not the /// type of trait objects (e.g. the fields are not directly accessible diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index eb7caa61972..575903d576a 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -185,7 +185,7 @@ //! [slice]: primitive.slice.html //! [`atomic`]: sync/atomic/index.html //! [`collections`]: collections/index.html -/// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for +//! [`for`]: ../book/ch03-05-control-flow.html#looping-through-a-collection-with-for //! [`format!`]: macro.format.html //! [`fs`]: fs/index.html //! [`io`]: io/index.html @@ -200,7 +200,7 @@ //! [`sync`]: sync/index.html //! [`thread`]: thread/index.html //! [`use std::env`]: env/index.html -//! [`use`]: ../book/ch07-02-modules-and-use-to-control-scope-and-privacy.html#use-to-bring-paths-into-scope +//! [`use`]: ../book/ch07-02-modules-and-use-to-control-scope-and-privacy.html#the-use-keyword-to-bring-paths-into-a-scope //! [crate root]: ../book/ch07-01-packages-and-crates-for-making-libraries-and-executables.html //! [crates.io]: https://crates.io //! [deref-coercions]: ../book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 15fbb105921..0995ab3c373 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -32,7 +32,7 @@ /// /// [`Result`] enum is often a better solution for recovering from errors than /// using the `panic!` macro. This macro should be used to avoid proceeding using -/// incorrect values, such as from external sources. Detailed information about +/// incorrect values, such as from external sources. Detailed information about /// error handling is found in the [book]. /// /// The multi-argument form of this macro panics with a string and has the @@ -45,7 +45,7 @@ /// [`Result`]: ../std/result/enum.Result.html /// [`format!`]: ../std/macro.format.html /// [`compile_error!`]: ../std/macro.compile_error.html -/// [book]: ../book/second-edition/ch09-01-unrecoverable-errors-with-panic.html +/// [book]: ../book/ch09-00-error-handling.html /// /// # Current implementation /// @@ -839,8 +839,8 @@ mod builtin { /// boolean expression evaluation of configuration flags. This frequently /// leads to less duplicated code. /// - /// The syntax given to this macro is the same syntax as [the `cfg` - /// attribute](../book/first-edition/conditional-compilation.html). + /// The syntax given to this macro is the same syntax as the `cfg` + /// attribute. /// /// # Examples /// @@ -915,7 +915,7 @@ mod builtin { /// Unsafe code relies on `assert!` to enforce run-time invariants that, if /// violated could lead to unsafety. /// - /// Other use-cases of `assert!` include [testing] and enforcing run-time + /// Other use-cases of `assert!` include testing and enforcing run-time /// invariants in safe code (whose violation cannot result in unsafety). /// /// # Custom Messages @@ -926,7 +926,6 @@ mod builtin { /// /// [`panic!`]: macro.panic.html /// [`debug_assert!`]: macro.debug_assert.html - /// [testing]: ../book/second-edition/ch11-01-writing-tests.html#checking-results-with-the-assert-macro /// [`std::fmt`]: ../std/fmt/index.html /// /// # Examples diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index c2a16122a0d..48acc1096a6 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -22,7 +22,7 @@ /// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc., /// which allow us to perform boolean operations using `&`, `|` and `!`. /// -/// [`if`] always demands a `bool` value. [`assert!`], being an important macro in testing, +/// `if` always demands a `bool` value. [`assert!`], being an important macro in testing, /// checks whether an expression returns `true`. /// /// ``` @@ -31,7 +31,6 @@ /// ``` /// /// [`assert!`]: macro.assert.html -/// [`if`]: ../book/first-edition/if.html /// [`BitAnd`]: ops/trait.BitAnd.html /// [`BitOr`]: ops/trait.BitOr.html /// [`Not`]: ops/trait.Not.html @@ -695,7 +694,7 @@ mod prim_str { } /// assert_eq!(tuple.2, 'c'); /// ``` /// -/// For more about tuples, see [the book](../book/first-edition/primitive-types.html#tuples). +/// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type). /// /// # Trait implementations /// From e8dafbaf10bf9e54854382f0aa830d219aec85bb Mon Sep 17 00:00:00 2001 From: Bastian Gruber Date: Wed, 21 Nov 2018 13:06:22 +0100 Subject: [PATCH 0113/1984] Adjust doc comments --- src/libstd/path.rs | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 9f6fcad2422..2d0a2501f7e 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1399,7 +1399,7 @@ impl<'a> From<&'a Path> for Box { impl From> for PathBuf { /// Converts a `Box` into a `PathBuf` /// - /// This conversion does not allocate memory + /// This conversion does not allocate or copy memory. fn from(boxed: Box) -> PathBuf { boxed.into_path_buf() } @@ -1409,7 +1409,8 @@ impl From> for PathBuf { impl From for Box { /// Converts a `PathBuf` into a `Box` /// - /// This conversion does not allocate memory + /// This conversion currently should not allocate memory, + // but this behavior is not guaranteed on all platforms or in all future versions. fn from(p: PathBuf) -> Box { p.into_boxed_path() } @@ -1434,7 +1435,7 @@ impl<'a, T: ?Sized + AsRef> From<&'a T> for PathBuf { impl From for PathBuf { /// Converts a `OsString` into a `PathBuf` /// - /// This conversion does not allocate memory + /// This conversion does not allocate or copy memory. fn from(s: OsString) -> PathBuf { PathBuf { inner: s } } @@ -1444,7 +1445,7 @@ impl From for PathBuf { impl From for OsString { /// Converts a `PathBuf` into a `OsString` /// - /// This conversion does not allocate memory + /// This conversion does not allocate or copy memory. fn from(path_buf : PathBuf) -> OsString { path_buf.inner } @@ -1454,7 +1455,7 @@ impl From for OsString { impl From for PathBuf { /// Converts a `String` into a `PathBuf` /// - /// This conversion does not allocate memory + /// This conversion does not allocate or copy memory. fn from(s: String) -> PathBuf { PathBuf::from(OsString::from(s)) } @@ -1551,11 +1552,7 @@ impl<'a> From> for PathBuf { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Arc { - /// Converts a `PathBuf` into a `Arc` - /// - /// This conversion happens in place - /// - /// This conversion does not allocate memory + /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. #[inline] fn from(s: PathBuf) -> Arc { let arc: Arc = Arc::from(s.into_os_string()); @@ -1565,12 +1562,7 @@ impl From for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl<'a> From<&'a Path> for Arc { - /// Converts a `PathBuf` into a `Arc` - /// - /// This conversion happens in place - /// - /// This conversion does not allocate memory - /// + /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. #[inline] fn from(s: &Path) -> Arc { let arc: Arc = Arc::from(s.as_os_str()); @@ -1580,11 +1572,7 @@ impl<'a> From<&'a Path> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { - /// Converts a `PathBuf` into a `Rc` - /// - /// This conversion happens in place - /// - /// This conversion does not allocate memory + /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. #[inline] fn from(s: PathBuf) -> Rc { let rc: Rc = Rc::from(s.into_os_string()); @@ -1594,6 +1582,7 @@ impl From for Rc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl<'a> From<&'a Path> for Rc { + /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. #[inline] fn from(s: &Path) -> Rc { let rc: Rc = Rc::from(s.as_os_str()); From 925274ab70c15ac5dcb3537e3473c29771ab7df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?= =?UTF-8?q?e=CC=B6r=20Scherer?= Date: Wed, 21 Nov 2018 13:10:10 +0100 Subject: [PATCH 0114/1984] Update as_temp.rs --- src/librustc_mir/build/expr/as_temp.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index f060eefe520..2db9fb9cb99 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -86,7 +86,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { unpack!(block = this.into(&Place::Local(temp), block, expr)); // In constants, temp_lifetime is None for temporaries that live for the - // entire constant. Thus we do not drop these temporaries and simply leak them. + // 'static lifetime. Thus we do not drop these temporaries and simply leak them. + // This is equivalent to what `let x = &foo();` does in functions. The temporary + // is lifted to their surrounding scope. In a function that means the temporary lives + // until just before the function returns. In constants that means it outlives the + // constant's initialization value computation. Anything outliving a constant + // must have the `'static` lifetime and live forever. // Anything with a shorter lifetime (e.g the `&foo()` in `bar(&foo())` or anything // within a block will keep the regular drops just like runtime code. if let Some(temp_lifetime) = temp_lifetime { From 7933628de58851281544fe2a7b4e0d0673652e47 Mon Sep 17 00:00:00 2001 From: Bastian Gruber Date: Wed, 21 Nov 2018 13:57:56 +0100 Subject: [PATCH 0115/1984] Remove trailing whitespace --- src/libstd/path.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 2d0a2501f7e..dcd02ac59b6 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1409,7 +1409,7 @@ impl From> for PathBuf { impl From for Box { /// Converts a `PathBuf` into a `Box` /// - /// This conversion currently should not allocate memory, + /// This conversion currently should not allocate memory, // but this behavior is not guaranteed on all platforms or in all future versions. fn from(p: PathBuf) -> Box { p.into_boxed_path() From 682b33a1103695de3c6520d55204b3c3d45f68ec Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Mon, 19 Nov 2018 00:15:41 +0900 Subject: [PATCH 0116/1984] Add require_type_is_sized_deferred. --- src/librustc_typeck/check/mod.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index aabef5c3234..b882d982c1f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -208,6 +208,10 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { fulfillment_cx: RefCell>>, + // Some additional `Sized` obligations badly affect type inference. + // These obligations are added in a later stage of typeck. + deferred_sized_obligations: RefCell, Span, traits::ObligationCauseCode<'tcx>)>>, + // When we process a call like `c()` where `c` is a closure type, // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or // `FnOnce` closure. In that case, we defer full resolution of the @@ -644,6 +648,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { infcx, fulfillment_cx: RefCell::new(TraitEngine::new(tcx)), locals: RefCell::new(Default::default()), + deferred_sized_obligations: RefCell::new(Vec::new()), deferred_call_resolutions: RefCell::new(Default::default()), deferred_cast_checks: RefCell::new(Vec::new()), deferred_generator_interiors: RefCell::new(Vec::new()), @@ -907,6 +912,10 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fcx.closure_analyze(body); assert!(fcx.deferred_call_resolutions.borrow().is_empty()); fcx.resolve_generator_interiors(def_id); + + for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) { + fcx.require_type_is_sized(ty, span, code); + } fcx.select_all_obligations_or_error(); if fn_decl.is_some() { @@ -2345,6 +2354,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.require_type_meets(ty, span, code, lang_item); } + pub fn require_type_is_sized_deferred(&self, + ty: Ty<'tcx>, + span: Span, + code: traits::ObligationCauseCode<'tcx>) + { + self.deferred_sized_obligations.borrow_mut().push((ty, span, code)); + } + pub fn register_bound(&self, ty: Ty<'tcx>, def_id: DefId, From 8b426232eef0629265bbfd0bc81fab75e113762b Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Mon, 19 Nov 2018 00:18:13 +0900 Subject: [PATCH 0117/1984] Check arg/ret sizedness at ExprKind::Path. --- src/librustc_typeck/check/mod.rs | 25 +++++++++++++++++++ src/test/ui/issues/issue-30355.nll.stderr | 22 ---------------- src/test/ui/issues/issue-30355.rs | 4 +-- src/test/ui/issues/issue-30355.stderr | 24 ++++++------------ src/test/ui/unsized-locals/unsized-exprs.rs | 2 ++ .../ui/unsized-locals/unsized-exprs.stderr | 13 +++++++++- src/test/ui/unsized-locals/unsized-exprs2.rs | 2 -- 7 files changed, 48 insertions(+), 44 deletions(-) delete mode 100644 src/test/ui/issues/issue-30355.nll.stderr diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b882d982c1f..572979d063d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3956,6 +3956,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.types.err }; + if let ty::FnDef(..) = ty.sty { + let fn_sig = ty.fn_sig(tcx); + if !tcx.features().unsized_locals { + // We want to remove some Sized bounds from std functions, + // but don't want to expose the removal to stable Rust. + // i.e. we don't want to allow + // + // ```rust + // drop as fn(str); + // ``` + // + // to work in stable even if the Sized bound on `drop` is relaxed. + for i in 0..fn_sig.inputs().skip_binder().len() { + let input = tcx.erase_late_bound_regions(&fn_sig.input(i)); + self.require_type_is_sized_deferred(input, expr.span, + traits::SizedArgumentType); + } + } + // Here we want to prevent struct constructors from returning unsized types. + // There were two cases this happened: fn pointer coercion in stable + // and usual function call in presense of unsized_locals. + let output = tcx.erase_late_bound_regions(&fn_sig.output()); + self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); + } + // We always require that the type provided as the value for // a type parameter outlives the moment of instantiation. let substs = self.tables.borrow().node_substs(expr.hir_id); diff --git a/src/test/ui/issues/issue-30355.nll.stderr b/src/test/ui/issues/issue-30355.nll.stderr deleted file mode 100644 index fdf8157dcf8..00000000000 --- a/src/test/ui/issues/issue-30355.nll.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0161]: cannot move a value of type X: the size of X cannot be statically determined - --> $DIR/issue-30355.rs:15:6 - | -LL | &X(*Y) - | ^^^^^ - -error[E0161]: cannot move a value of type [u8]: the size of [u8] cannot be statically determined - --> $DIR/issue-30355.rs:15:8 - | -LL | &X(*Y) - | ^^ - -error[E0508]: cannot move out of type `[u8]`, a non-copy slice - --> $DIR/issue-30355.rs:15:8 - | -LL | &X(*Y) - | ^^ cannot move out of here - -error: aborting due to 3 previous errors - -Some errors occurred: E0161, E0508. -For more information about an error, try `rustc --explain E0161`. diff --git a/src/test/ui/issues/issue-30355.rs b/src/test/ui/issues/issue-30355.rs index ee19d040318..8d5eac06c43 100644 --- a/src/test/ui/issues/issue-30355.rs +++ b/src/test/ui/issues/issue-30355.rs @@ -13,9 +13,7 @@ pub struct X([u8]); pub static Y: &'static X = { const Y: &'static [u8] = b""; &X(*Y) - //~^ ERROR cannot move out - //~^^ ERROR cannot move a - //~^^^ ERROR cannot move a + //~^ ERROR E0277 }; fn main() {} diff --git a/src/test/ui/issues/issue-30355.stderr b/src/test/ui/issues/issue-30355.stderr index 7e843688035..1b55f20e6b4 100644 --- a/src/test/ui/issues/issue-30355.stderr +++ b/src/test/ui/issues/issue-30355.stderr @@ -1,22 +1,14 @@ -error[E0161]: cannot move a value of type X: the size of X cannot be statically determined +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/issue-30355.rs:15:6 | LL | &X(*Y) - | ^^^^^ - -error[E0161]: cannot move a value of type [u8]: the size of [u8] cannot be statically determined - --> $DIR/issue-30355.rs:15:8 + | ^ doesn't have a size known at compile-time | -LL | &X(*Y) - | ^^ - -error[E0507]: cannot move out of borrowed content - --> $DIR/issue-30355.rs:15:8 - | -LL | &X(*Y) - | ^^ cannot move out of borrowed content + = help: the trait `std::marker::Sized` is not implemented for `[u8]` + = note: to learn more, visit + = note: all function arguments must have a statically known size + = help: unsized locals are gated as an unstable feature -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors occurred: E0161, E0507. -For more information about an error, try `rustc --explain E0161`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsized-locals/unsized-exprs.rs b/src/test/ui/unsized-locals/unsized-exprs.rs index 0cf93c78c4a..8ca88edcb6a 100644 --- a/src/test/ui/unsized-locals/unsized-exprs.rs +++ b/src/test/ui/unsized-locals/unsized-exprs.rs @@ -23,4 +23,6 @@ fn main() { //~^ERROR E0277 udrop::>(A { 0: *foo() }); //~^ERROR E0277 + udrop::>(A(*foo())); + //~^ERROR E0277 } diff --git a/src/test/ui/unsized-locals/unsized-exprs.stderr b/src/test/ui/unsized-locals/unsized-exprs.stderr index eb201694177..0ca60e8dea0 100644 --- a/src/test/ui/unsized-locals/unsized-exprs.stderr +++ b/src/test/ui/unsized-locals/unsized-exprs.stderr @@ -20,6 +20,17 @@ LL | udrop::>(A { 0: *foo() }); = note: required because it appears within the type `A<[u8]>` = note: structs must have a statically known size to be initialized -error: aborting due to 2 previous errors +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-exprs.rs:26:22 + | +LL | udrop::>(A(*foo())); + | ^ doesn't have a size known at compile-time + | + = help: within `A<[u8]>`, the trait `std::marker::Sized` is not implemented for `[u8]` + = note: to learn more, visit + = note: required because it appears within the type `A<[u8]>` + = note: the return type of a function must have a statically known size + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsized-locals/unsized-exprs2.rs b/src/test/ui/unsized-locals/unsized-exprs2.rs index ae69893a835..3fb5a002e0e 100644 --- a/src/test/ui/unsized-locals/unsized-exprs2.rs +++ b/src/test/ui/unsized-locals/unsized-exprs2.rs @@ -21,6 +21,4 @@ impl std::ops::Add for A<[u8]> { fn main() { udrop::<[u8]>(foo()[..]); //~^ERROR cannot move out of indexed content - // FIXME: should be error - udrop::>(A(*foo())); } From 8ab5be13a31261317c0e4b52bd4743da03e5bf74 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Mon, 19 Nov 2018 00:19:14 +0900 Subject: [PATCH 0118/1984] Add tests verifying #50940. --- .../ui/unsized-locals/issue-50940-with-feature.rs | 7 +++++++ .../unsized-locals/issue-50940-with-feature.stderr | 14 ++++++++++++++ src/test/ui/unsized-locals/issue-50940.rs | 5 +++++ src/test/ui/unsized-locals/issue-50940.stderr | 14 ++++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 src/test/ui/unsized-locals/issue-50940-with-feature.rs create mode 100644 src/test/ui/unsized-locals/issue-50940-with-feature.stderr create mode 100644 src/test/ui/unsized-locals/issue-50940.rs create mode 100644 src/test/ui/unsized-locals/issue-50940.stderr diff --git a/src/test/ui/unsized-locals/issue-50940-with-feature.rs b/src/test/ui/unsized-locals/issue-50940-with-feature.rs new file mode 100644 index 00000000000..3e5d39ab311 --- /dev/null +++ b/src/test/ui/unsized-locals/issue-50940-with-feature.rs @@ -0,0 +1,7 @@ +#![feature(unsized_locals)] + +fn main() { + struct A(X); + A as fn(str) -> A; + //~^ERROR the size for values of type `str` cannot be known at compilation time +} diff --git a/src/test/ui/unsized-locals/issue-50940-with-feature.stderr b/src/test/ui/unsized-locals/issue-50940-with-feature.stderr new file mode 100644 index 00000000000..f4f015fa190 --- /dev/null +++ b/src/test/ui/unsized-locals/issue-50940-with-feature.stderr @@ -0,0 +1,14 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/issue-50940-with-feature.rs:5:5 + | +LL | A as fn(str) -> A; + | ^ doesn't have a size known at compile-time + | + = help: within `main::A`, the trait `std::marker::Sized` is not implemented for `str` + = note: to learn more, visit + = note: required because it appears within the type `main::A` + = note: the return type of a function must have a statically known size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsized-locals/issue-50940.rs b/src/test/ui/unsized-locals/issue-50940.rs new file mode 100644 index 00000000000..7ba809b7e83 --- /dev/null +++ b/src/test/ui/unsized-locals/issue-50940.rs @@ -0,0 +1,5 @@ +fn main() { + struct A(X); + A as fn(str) -> A; + //~^ERROR the size for values of type `str` cannot be known at compilation time +} diff --git a/src/test/ui/unsized-locals/issue-50940.stderr b/src/test/ui/unsized-locals/issue-50940.stderr new file mode 100644 index 00000000000..9f3669ccf1f --- /dev/null +++ b/src/test/ui/unsized-locals/issue-50940.stderr @@ -0,0 +1,14 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/issue-50940.rs:3:5 + | +LL | A as fn(str) -> A; + | ^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `str` + = note: to learn more, visit + = note: all function arguments must have a statically known size + = help: unsized locals are gated as an unstable feature + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 2ff6ffc872645bf6f5bc7dda4a817a1fc7789684 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Mon, 19 Nov 2018 00:26:05 +0900 Subject: [PATCH 0119/1984] Add tests for unsized-locals functions stability. --- src/test/run-pass/unsized-locals/unsized-exprs.rs | 1 + src/test/ui/unsized-locals/auxiliary/ufuncs.rs | 3 +++ src/test/ui/unsized-locals/unsized-exprs3.rs | 10 ++++++++++ src/test/ui/unsized-locals/unsized-exprs3.stderr | 14 ++++++++++++++ 4 files changed, 28 insertions(+) create mode 100644 src/test/ui/unsized-locals/auxiliary/ufuncs.rs create mode 100644 src/test/ui/unsized-locals/unsized-exprs3.rs create mode 100644 src/test/ui/unsized-locals/unsized-exprs3.stderr diff --git a/src/test/run-pass/unsized-locals/unsized-exprs.rs b/src/test/run-pass/unsized-locals/unsized-exprs.rs index 4b988f1e72d..bc64fcdec2e 100644 --- a/src/test/run-pass/unsized-locals/unsized-exprs.rs +++ b/src/test/run-pass/unsized-locals/unsized-exprs.rs @@ -34,4 +34,5 @@ fn main() { udrop::<[u8]>((*foo())); udrop::<[u8]>((*tfoo()).1); *afoo() + 42; + udrop as fn([u8]); } diff --git a/src/test/ui/unsized-locals/auxiliary/ufuncs.rs b/src/test/ui/unsized-locals/auxiliary/ufuncs.rs new file mode 100644 index 00000000000..065563d45a4 --- /dev/null +++ b/src/test/ui/unsized-locals/auxiliary/ufuncs.rs @@ -0,0 +1,3 @@ +#![feature(unsized_locals)] + +pub fn udrop(_x: T) {} diff --git a/src/test/ui/unsized-locals/unsized-exprs3.rs b/src/test/ui/unsized-locals/unsized-exprs3.rs new file mode 100644 index 00000000000..2133b01e094 --- /dev/null +++ b/src/test/ui/unsized-locals/unsized-exprs3.rs @@ -0,0 +1,10 @@ +// aux-build:ufuncs.rs + +extern crate ufuncs; + +use ufuncs::udrop; + +fn main() { + udrop as fn([u8]); + //~^ERROR E0277 +} diff --git a/src/test/ui/unsized-locals/unsized-exprs3.stderr b/src/test/ui/unsized-locals/unsized-exprs3.stderr new file mode 100644 index 00000000000..42f91a946a8 --- /dev/null +++ b/src/test/ui/unsized-locals/unsized-exprs3.stderr @@ -0,0 +1,14 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-exprs3.rs:8:5 + | +LL | udrop as fn([u8]); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `[u8]` + = note: to learn more, visit + = note: all function arguments must have a statically known size + = help: unsized locals are gated as an unstable feature + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From c6a803a286faae901a6ebd35ec222901f691c7ec Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Mon, 19 Nov 2018 00:27:16 +0900 Subject: [PATCH 0120/1984] Modify doc to reflect the unsized-locals improvement. --- src/doc/unstable-book/src/language-features/unsized-locals.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/unsized-locals.md b/src/doc/unstable-book/src/language-features/unsized-locals.md index 6f7cf754ae0..1165ab93a14 100644 --- a/src/doc/unstable-book/src/language-features/unsized-locals.md +++ b/src/doc/unstable-book/src/language-features/unsized-locals.md @@ -80,8 +80,6 @@ fn main() { } ``` -However, the current implementation allows `MyTupleStruct(..)` to be unsized. This will be fixed in the future. - ## By-value trait objects With this feature, you can have by-value `self` arguments without `Self: Sized` bounds. From 33efce1c2f280848a84b94f99ea1bc874e189a37 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 21 Nov 2018 14:27:30 +0100 Subject: [PATCH 0121/1984] Forward rust version number to tools Clippy uses it to identify the correct documentation to point to --- src/bootstrap/tool.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 978e3602e7d..d8e86644ee0 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -22,6 +22,7 @@ use util::{exe, add_lib_path}; use compile; use native; use channel::GitInfo; +use channel; use cache::Interned; use toolstate::ToolState; @@ -240,6 +241,7 @@ pub fn prepare_tool_cargo( cargo.env("CFG_RELEASE_CHANNEL", &builder.config.channel); cargo.env("CFG_VERSION", builder.rust_version()); + cargo.env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM); let info = GitInfo::new(&builder.config, &dir); if let Some(sha) = info.sha() { From f03987276656134f25f92f7434d7d1c63c9e981c Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 21 Nov 2018 16:06:24 +0000 Subject: [PATCH 0122/1984] Enclose type in backticks for "reached the recursion limit while auto-dereferencing" error --- src/librustc_typeck/check/autoderef.rs | 4 ++-- src/librustc_typeck/diagnostics.rs | 2 +- src/test/ui/did_you_mean/recursion_limit_deref.stderr | 2 +- src/test/ui/error-codes/E0055.stderr | 2 +- src/test/ui/infinite/infinite-autoderef.stderr | 6 +++--- src/test/ui/issues/issue-38940.rs | 2 +- src/test/ui/issues/issue-38940.stderr | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 73489309d07..2cd2bb50648 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -59,7 +59,7 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> { if self.steps.len() >= *tcx.sess.recursion_limit.get() { // We've reached the recursion limit, error gracefully. let suggested_limit = *tcx.sess.recursion_limit.get() * 2; - let msg = format!("reached the recursion limit while auto-dereferencing {:?}", + let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", self.cur_ty); let error_id = (DiagnosticMessageId::ErrorId(55), Some(self.span), msg); let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); @@ -67,7 +67,7 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> { struct_span_err!(tcx.sess, self.span, E0055, - "reached the recursion limit while auto-dereferencing {:?}", + "reached the recursion limit while auto-dereferencing `{:?}`", self.cur_ty) .span_label(self.span, "deref recursion limit reached") .help(&format!( diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index a985c3e9fdf..084951f4a2c 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -538,7 +538,7 @@ fn main() { let foo = Foo; let ref_foo = &&Foo; - // error, reached the recursion limit while auto-dereferencing &&Foo + // error, reached the recursion limit while auto-dereferencing `&&Foo` ref_foo.foo(); } ``` diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr index 20a94f7aac1..7e7f21dd69c 100644 --- a/src/test/ui/did_you_mean/recursion_limit_deref.stderr +++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr @@ -1,4 +1,4 @@ -error[E0055]: reached the recursion limit while auto-dereferencing I +error[E0055]: reached the recursion limit while auto-dereferencing `I` --> $DIR/recursion_limit_deref.rs:60:22 | LL | let x: &Bottom = &t; //~ ERROR mismatched types diff --git a/src/test/ui/error-codes/E0055.stderr b/src/test/ui/error-codes/E0055.stderr index 9653f4eaeef..dddbd92765a 100644 --- a/src/test/ui/error-codes/E0055.stderr +++ b/src/test/ui/error-codes/E0055.stderr @@ -1,4 +1,4 @@ -error[E0055]: reached the recursion limit while auto-dereferencing Foo +error[E0055]: reached the recursion limit while auto-dereferencing `Foo` --> $DIR/E0055.rs:21:13 | LL | ref_foo.foo(); diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr index b5e20ea5cbf..ef68adecd1a 100644 --- a/src/test/ui/infinite/infinite-autoderef.stderr +++ b/src/test/ui/infinite/infinite-autoderef.stderr @@ -7,7 +7,7 @@ LL | x = box x; | cyclic type of infinite size | help: try using a conversion method: `box x.to_string()` -error[E0055]: reached the recursion limit while auto-dereferencing Foo +error[E0055]: reached the recursion limit while auto-dereferencing `Foo` --> $DIR/infinite-autoderef.rs:35:5 | LL | Foo.foo; @@ -15,7 +15,7 @@ LL | Foo.foo; | = help: consider adding a `#![recursion_limit="128"]` attribute to your crate -error[E0055]: reached the recursion limit while auto-dereferencing Foo +error[E0055]: reached the recursion limit while auto-dereferencing `Foo` --> $DIR/infinite-autoderef.rs:35:9 | LL | Foo.foo; @@ -29,7 +29,7 @@ error[E0609]: no field `foo` on type `Foo` LL | Foo.foo; | ^^^ unknown field -error[E0055]: reached the recursion limit while auto-dereferencing Foo +error[E0055]: reached the recursion limit while auto-dereferencing `Foo` --> $DIR/infinite-autoderef.rs:36:9 | LL | Foo.bar(); diff --git a/src/test/ui/issues/issue-38940.rs b/src/test/ui/issues/issue-38940.rs index 7f9b141e02e..1c785949547 100644 --- a/src/test/ui/issues/issue-38940.rs +++ b/src/test/ui/issues/issue-38940.rs @@ -42,5 +42,5 @@ fn main() { let t = Top::new(); let x: &Bottom = &t; //~^ ERROR mismatched types - //~| ERROR reached the recursion limit while auto-dereferencing I + //~| ERROR reached the recursion limit while auto-dereferencing `I` } diff --git a/src/test/ui/issues/issue-38940.stderr b/src/test/ui/issues/issue-38940.stderr index 2d3cfda9a5f..d94a7101c0a 100644 --- a/src/test/ui/issues/issue-38940.stderr +++ b/src/test/ui/issues/issue-38940.stderr @@ -1,4 +1,4 @@ -error[E0055]: reached the recursion limit while auto-dereferencing I +error[E0055]: reached the recursion limit while auto-dereferencing `I` --> $DIR/issue-38940.rs:43:22 | LL | let x: &Bottom = &t; From 0591ff7525d3d468244e102c4002b6663db5f5ad Mon Sep 17 00:00:00 2001 From: Lyndon Brown Date: Sat, 10 Nov 2018 06:59:42 +0000 Subject: [PATCH 0123/1984] OsString: mention storage form in discussion Helps users to understand capacity related values, which may surpise on Windows. Also is a step towards clarifying understanding of `OsStr`'s len() return value. --- src/libstd/ffi/os_str.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index e9390630445..d5a51c02a47 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -42,6 +42,13 @@ use sys_common::{AsInner, IntoInner, FromInner}; /// in each pair are owned strings; the latter are borrowed /// references. /// +/// Note, `OsString` and `OsStr` internally do not necessarily hold strings in +/// the form native to the platform; While on Unix, strings are stored as a +/// sequence of 8-bit values, on Windows, where strings are 16-bit value based +/// as just discussed, strings are also actually stored as a sequence of 8-bit +/// values, encoded in a less-strict variant of UTF-8. This is useful to +/// understand when handling capacity and length values. +/// /// # Creating an `OsString` /// /// **From a Rust string**: `OsString` implements From a1e9c7fc2e4806fe72c84178bf1116f645d18c43 Mon Sep 17 00:00:00 2001 From: Lyndon Brown Date: Sat, 10 Nov 2018 07:35:15 +0000 Subject: [PATCH 0124/1984] OsStr: clarify `len()` method documentation --- src/libstd/ffi/os_str.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index d5a51c02a47..0edfd122cef 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -590,14 +590,19 @@ impl OsStr { /// Returns the length of this `OsStr`. /// - /// Note that this does **not** return the number of bytes in this string - /// as, for example, OS strings on Windows are encoded as a list of [`u16`] - /// rather than a list of bytes. This number is simply useful for passing to - /// other methods like [`OsString::with_capacity`] to avoid reallocations. + /// Note that this does **not** return the number of bytes in the string in + /// OS string form. /// - /// See `OsStr` introduction for more information about encoding. + /// The length returned is that of the underlying storage used by `OsStr`; + /// As discussed in the [`OsString`] introduction, [`OsString`] and `OsStr` + /// store strings in a form best suited for cheap inter-conversion between + /// native-platform and Rust string forms, which may differ significantly + /// from both of them, including in storage size and encoding. /// - /// [`u16`]: ../primitive.u16.html + /// This number is simply useful for passing to other methods, like + /// [`OsString::with_capacity`] to avoid reallocations. + /// + /// [`OsString`]: struct.OsString.html /// [`OsString::with_capacity`]: struct.OsString.html#method.with_capacity /// /// # Examples From d0a174d41b230dc2cb08a902c2ecca0d89ee7856 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 21 Nov 2018 13:35:14 -0500 Subject: [PATCH 0125/1984] track the span for each id so that we can give a nice ICE --- src/librustc/hir/map/collector.rs | 64 ++++++++++++++++++------------- src/librustc/hir/map/mod.rs | 4 +- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 4fbcd83adb5..2917fd7457a 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -28,6 +28,10 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHashe pub(super) struct NodeCollector<'a, 'hir> { /// The crate krate: &'hir Crate, + + /// Source map + source_map: &'a SourceMap, + /// The node map map: Vec>>, /// The parent of this node @@ -54,7 +58,8 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { pub(super) fn root(krate: &'hir Crate, dep_graph: &'a DepGraph, definitions: &'a definitions::Definitions, - hcx: StableHashingContext<'a>) + hcx: StableHashingContext<'a>, + source_map: &'a SourceMap) -> NodeCollector<'a, 'hir> { let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX); @@ -102,6 +107,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let mut collector = NodeCollector { krate, + source_map, map: vec![], parent_node: CRATE_NODE_ID, current_signature_dep_index: root_mod_sig_dep_index, @@ -125,7 +131,6 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { pub(super) fn finalize_and_compute_crate_hash(mut self, crate_disambiguator: CrateDisambiguator, cstore: &dyn CrateStore, - source_map: &SourceMap, commandline_args_hash: u64) -> (Vec>>, Svh) { @@ -154,7 +159,8 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { // If we included the full mapping in the SVH, we could only have // reproducible builds by compiling from the same directory. So we just // hash the result of the mapping instead of the mapping itself. - let mut source_file_names: Vec<_> = source_map + let mut source_file_names: Vec<_> = self + .source_map .files() .iter() .filter(|source_file| CrateNum::from_u32(source_file.crate_of_origin) == LOCAL_CRATE) @@ -186,7 +192,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { self.map[id.as_usize()] = Some(entry); } - fn insert(&mut self, id: NodeId, node: Node<'hir>) { + fn insert(&mut self, span: Span, id: NodeId, node: Node<'hir>) { let entry = Entry { parent: self.parent_node, dep_node: if self.currently_in_body { @@ -216,8 +222,11 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { String::new() }; - bug!("inconsistent DepNode for `{}`: \ - current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?}){}", + span_bug!( + span, + "inconsistent DepNode at `{:?}` for `{}`: \ + current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?}){}", + self.source_map.span_to_string(span), node_str, self.definitions .def_path(self.current_dep_node_owner) @@ -225,7 +234,8 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { self.current_dep_node_owner, self.definitions.def_path(hir_id.owner).to_string_no_crate(), hir_id.owner, - forgot_str) + forgot_str, + ) } } @@ -309,12 +319,12 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { debug_assert_eq!(i.hir_id.owner, self.definitions.opt_def_index(i.id).unwrap()); self.with_dep_node_owner(i.hir_id.owner, i, |this| { - this.insert(i.id, Node::Item(i)); + this.insert(i.span, i.id, Node::Item(i)); this.with_parent(i.id, |this| { if let ItemKind::Struct(ref struct_def, _) = i.node { // If this is a tuple-like struct, register the constructor. if !struct_def.is_struct() { - this.insert(struct_def.id(), Node::StructCtor(struct_def)); + this.insert(i.span, struct_def.id(), Node::StructCtor(struct_def)); } } intravisit::walk_item(this, i); @@ -323,7 +333,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem) { - self.insert(foreign_item.id, Node::ForeignItem(foreign_item)); + self.insert(foreign_item.span, foreign_item.id, Node::ForeignItem(foreign_item)); self.with_parent(foreign_item.id, |this| { intravisit::walk_foreign_item(this, foreign_item); @@ -331,7 +341,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_generic_param(&mut self, param: &'hir GenericParam) { - self.insert(param.id, Node::GenericParam(param)); + self.insert(param.span, param.id, Node::GenericParam(param)); intravisit::walk_generic_param(self, param); } @@ -339,7 +349,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { debug_assert_eq!(ti.hir_id.owner, self.definitions.opt_def_index(ti.id).unwrap()); self.with_dep_node_owner(ti.hir_id.owner, ti, |this| { - this.insert(ti.id, Node::TraitItem(ti)); + this.insert(ti.span, ti.id, Node::TraitItem(ti)); this.with_parent(ti.id, |this| { intravisit::walk_trait_item(this, ti); @@ -351,7 +361,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { debug_assert_eq!(ii.hir_id.owner, self.definitions.opt_def_index(ii.id).unwrap()); self.with_dep_node_owner(ii.hir_id.owner, ii, |this| { - this.insert(ii.id, Node::ImplItem(ii)); + this.insert(ii.span, ii.id, Node::ImplItem(ii)); this.with_parent(ii.id, |this| { intravisit::walk_impl_item(this, ii); @@ -365,7 +375,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } else { Node::Pat(pat) }; - self.insert(pat.id, node); + self.insert(pat.span, pat.id, node); self.with_parent(pat.id, |this| { intravisit::walk_pat(this, pat); @@ -373,7 +383,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_anon_const(&mut self, constant: &'hir AnonConst) { - self.insert(constant.id, Node::AnonConst(constant)); + self.insert(DUMMY_SP, constant.id, Node::AnonConst(constant)); self.with_parent(constant.id, |this| { intravisit::walk_anon_const(this, constant); @@ -381,7 +391,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_expr(&mut self, expr: &'hir Expr) { - self.insert(expr.id, Node::Expr(expr)); + self.insert(expr.span, expr.id, Node::Expr(expr)); self.with_parent(expr.id, |this| { intravisit::walk_expr(this, expr); @@ -390,7 +400,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_stmt(&mut self, stmt: &'hir Stmt) { let id = stmt.node.id(); - self.insert(id, Node::Stmt(stmt)); + self.insert(stmt.span, id, Node::Stmt(stmt)); self.with_parent(id, |this| { intravisit::walk_stmt(this, stmt); @@ -399,13 +409,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_path_segment(&mut self, path_span: Span, path_segment: &'hir PathSegment) { if let Some(id) = path_segment.id { - self.insert(id, Node::PathSegment(path_segment)); + self.insert(path_span, id, Node::PathSegment(path_segment)); } intravisit::walk_path_segment(self, path_span, path_segment); } fn visit_ty(&mut self, ty: &'hir Ty) { - self.insert(ty.id, Node::Ty(ty)); + self.insert(ty.span, ty.id, Node::Ty(ty)); self.with_parent(ty.id, |this| { intravisit::walk_ty(this, ty); @@ -413,7 +423,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_trait_ref(&mut self, tr: &'hir TraitRef) { - self.insert(tr.ref_id, Node::TraitRef(tr)); + self.insert(tr.path.span, tr.ref_id, Node::TraitRef(tr)); self.with_parent(tr.ref_id, |this| { intravisit::walk_trait_ref(this, tr); @@ -427,21 +437,21 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_block(&mut self, block: &'hir Block) { - self.insert(block.id, Node::Block(block)); + self.insert(block.span, block.id, Node::Block(block)); self.with_parent(block.id, |this| { intravisit::walk_block(this, block); }); } fn visit_local(&mut self, l: &'hir Local) { - self.insert(l.id, Node::Local(l)); + self.insert(l.span, l.id, Node::Local(l)); self.with_parent(l.id, |this| { intravisit::walk_local(this, l) }) } fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) { - self.insert(lifetime.id, Node::Lifetime(lifetime)); + self.insert(lifetime.span, lifetime.id, Node::Lifetime(lifetime)); } fn visit_vis(&mut self, visibility: &'hir Visibility) { @@ -450,7 +460,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { VisibilityKind::Crate(_) | VisibilityKind::Inherited => {} VisibilityKind::Restricted { id, .. } => { - self.insert(id, Node::Visibility(visibility)); + self.insert(visibility.span, id, Node::Visibility(visibility)); self.with_parent(id, |this| { intravisit::walk_vis(this, visibility); }); @@ -462,20 +472,20 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { let def_index = self.definitions.opt_def_index(macro_def.id).unwrap(); self.with_dep_node_owner(def_index, macro_def, |this| { - this.insert(macro_def.id, Node::MacroDef(macro_def)); + this.insert(macro_def.span, macro_def.id, Node::MacroDef(macro_def)); }); } fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: NodeId) { let id = v.node.data.id(); - self.insert(id, Node::Variant(v)); + self.insert(v.span, id, Node::Variant(v)); self.with_parent(id, |this| { intravisit::walk_variant(this, v, g, item_id); }); } fn visit_struct_field(&mut self, field: &'hir StructField) { - self.insert(field.id, Node::Field(field)); + self.insert(field.span, field.id, Node::Field(field)); self.with_parent(field.id, |this| { intravisit::walk_struct_field(this, field); }); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index cf7a7abf95a..ef777abfbc4 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1032,14 +1032,14 @@ pub fn map_crate<'hir>(sess: &::session::Session, let mut collector = NodeCollector::root(&forest.krate, &forest.dep_graph, &definitions, - hcx); + hcx, + sess.source_map()); intravisit::walk_crate(&mut collector, &forest.krate); let crate_disambiguator = sess.local_crate_disambiguator(); let cmdline_args = sess.opts.dep_tracking_hash(); collector.finalize_and_compute_crate_hash(crate_disambiguator, cstore, - sess.source_map(), cmdline_args) }; From 40f80940035af4b44aa7846ed34abee71151d3ee Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 21 Nov 2018 13:35:54 -0500 Subject: [PATCH 0126/1984] add some `debug!` into lowering --- src/librustc/hir/lowering.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 7ac3b033437..e4819d6fb1d 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1866,6 +1866,10 @@ impl<'a> LoweringContext<'a> { } else { self.lower_node_id(segment.id) }; + debug!( + "lower_path_segment: ident={:?} original-id={:?} new-id={:?}", + segment.ident, segment.id, id, + ); hir::PathSegment::new( segment.ident, @@ -2955,6 +2959,9 @@ impl<'a> LoweringContext<'a> { name: &mut Name, attrs: &hir::HirVec, ) -> hir::ItemKind { + debug!("lower_use_tree(tree={:?})", tree); + debug!("lower_use_tree: vis = {:?}", vis); + let path = &tree.prefix; let segments = prefix .segments @@ -4540,6 +4547,7 @@ impl<'a> LoweringContext<'a> { VisibilityKind::Public => hir::VisibilityKind::Public, VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar), VisibilityKind::Restricted { ref path, id } => { + debug!("lower_visibility: restricted path id = {:?}", id); let lowered_id = if let Some(owner) = explicit_owner { self.lower_node_id_with_owner(id, owner) } else { From a0a47904d64031a7a24828d6ad368ea9da33082a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 21 Nov 2018 13:36:11 -0500 Subject: [PATCH 0127/1984] renumber segment ids for visibilities whenever we clone them --- src/librustc/hir/lowering.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e4819d6fb1d..79d605c0035 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3029,12 +3029,7 @@ impl<'a> LoweringContext<'a> { hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited, hir::VisibilityKind::Restricted { ref path, id: _, hir_id: _ } => { let id = this.next_id(); - let mut path = path.clone(); - for seg in path.segments.iter_mut() { - if seg.id.is_some() { - seg.id = Some(this.next_id().node_id); - } - } + let path = this.renumber_segment_ids(path); hir::VisibilityKind::Restricted { path, id: id.node_id, @@ -3119,8 +3114,9 @@ impl<'a> LoweringContext<'a> { hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited, hir::VisibilityKind::Restricted { ref path, id: _, hir_id: _ } => { let id = this.next_id(); + let path = this.renumber_segment_ids(path); hir::VisibilityKind::Restricted { - path: path.clone(), + path: path, id: id.node_id, hir_id: id.hir_id, } @@ -3154,6 +3150,20 @@ impl<'a> LoweringContext<'a> { } } + /// Paths like the visibility path in `pub(super) use foo::{bar, baz}` are repeated + /// many times in the HIR tree; for each occurrence, we need to assign distinct + /// node-ids. (See e.g. #56128.) + fn renumber_segment_ids(&mut self, path: &P) -> P { + debug!("renumber_segment_ids(path = {:?})", path); + let mut path = path.clone(); + for seg in path.segments.iter_mut() { + if seg.id.is_some() { + seg.id = Some(self.next_id().node_id); + } + } + path + } + fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem { let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id); let trait_item_def_id = self.resolver.definitions().local_def_id(node_id); From c209ed84359804d200454f117946d41e5ac84159 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 1 Nov 2018 02:20:49 +0100 Subject: [PATCH 0128/1984] Improve no result found sentence in doc search --- src/librustdoc/html/static/main.js | 11 ++++++++++- src/librustdoc/html/static/rustdoc.css | 13 ++++++++++--- src/librustdoc/html/static/themes/dark.css | 2 +- src/librustdoc/html/static/themes/light.css | 2 +- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 3174c1be3ad..27b1dfc9ce3 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1340,7 +1340,16 @@ output = '
No results :(
' + 'Try on DuckDuckGo?
'; + '">DuckDuckGo?

' + + 'Or try looking in one of these:'; } return [output, length]; } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 8bcb828a5ad..aa43a0bb58a 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -658,9 +658,9 @@ a { padding-right: 10px; } .content .search-results td:first-child a:after { - clear: both; - content: ""; - display: block; + clear: both; + content: ""; + display: block; } .content .search-results td:first-child a span { float: left; @@ -1116,6 +1116,13 @@ pre.rust { margin-top: 20px; } +.search-failed > ul { + text-align: left; + max-width: 570px; + margin-left: auto; + margin-right: auto; +} + #titles { height: 35px; } diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 4a8950b236c..9c90c948581 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -285,7 +285,7 @@ pre.ignore:hover, .information:hover + pre.ignore { color: rgba(255,142,0,1); } -.search-failed > a { +.search-failed a { color: #0089ff; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index b3b0b6b2ea9..e839fc3f278 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -279,7 +279,7 @@ pre.ignore:hover, .information:hover + pre.ignore { color: rgba(255,142,0,1); } -.search-failed > a { +.search-failed a { color: #0089ff; } From 5af8f1d8d7e78722eb7c89e3f0459ab81c3aebbc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 4 Nov 2018 21:35:09 +0100 Subject: [PATCH 0129/1984] Fixes primitive sidebar link generation --- src/librustdoc/html/render.rs | 87 +++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 30 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index f560350d510..1ce7c9cfc8a 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -4234,13 +4234,30 @@ impl<'a> fmt::Display for Sidebar<'a> { } } -fn get_methods(i: &clean::Impl, for_deref: bool) -> Vec { +fn get_next_url(used_links: &mut FxHashSet, url: String) -> String { + if used_links.insert(url.clone()) { + return url; + } + let mut add = 1; + while used_links.insert(format!("{}-{}", url, add)) == false { + add += 1; + } + format!("{}-{}", url, add) +} + +fn get_methods( + i: &clean::Impl, + for_deref: bool, + used_links: &mut FxHashSet, +) -> Vec { i.items.iter().filter_map(|item| { match item.name { // Maybe check with clean::Visibility::Public as well? Some(ref name) if !name.is_empty() && item.visibility.is_some() && item.is_method() => { if !for_deref || should_render_item(item, false) { - Some(format!("{name}", name = name)) + Some(format!("{}", + get_next_url(used_links, format!("method.{}", name)), + name)) } else { None } @@ -4270,13 +4287,20 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { let mut out = String::new(); let c = cache(); if let Some(v) = c.impls.get(&it.def_id) { - let ret = v.iter() - .filter(|i| i.inner_impl().trait_.is_none()) - .flat_map(|i| get_methods(i.inner_impl(), false)) - .collect::(); - if !ret.is_empty() { - out.push_str(&format!("Methods\ -
{}
", ret)); + let mut used_links = FxHashSet::default(); + + { + let used_links_bor = Rc::new(RefCell::new(&mut used_links)); + let ret = v.iter() + .filter(|i| i.inner_impl().trait_.is_none()) + .flat_map(move |i| get_methods(i.inner_impl(), + false, + &mut used_links_bor.borrow_mut())) + .collect::(); + if !ret.is_empty() { + out.push_str(&format!("Methods\ +
{}
", ret)); + } } if v.iter().any(|i| i.inner_impl().trait_.is_some()) { @@ -4301,7 +4325,9 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { out.push_str(""); let ret = impls.iter() .filter(|i| i.inner_impl().trait_.is_none()) - .flat_map(|i| get_methods(i.inner_impl(), true)) + .flat_map(|i| get_methods(i.inner_impl(), + true, + &mut used_links)) .collect::(); out.push_str(&format!("
{}
", ret)); } @@ -4309,27 +4335,28 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { } let format_impls = |impls: Vec<&Impl>| { let mut links = FxHashSet::default(); + impls.iter() - .filter_map(|i| { - let is_negative_impl = is_negative_impl(i.inner_impl()); - if let Some(ref i) = i.inner_impl().trait_ { - let i_display = format!("{:#}", i); - let out = Escape(&i_display); - let encoded = small_url_encode(&format!("{:#}", i)); - let generated = format!("{}{}", - encoded, - if is_negative_impl { "!" } else { "" }, - out); - if links.insert(generated.clone()) { - Some(generated) - } else { - None - } - } else { - None - } - }) - .collect::() + .filter_map(|i| { + let is_negative_impl = is_negative_impl(i.inner_impl()); + if let Some(ref i) = i.inner_impl().trait_ { + let i_display = format!("{:#}", i); + let out = Escape(&i_display); + let encoded = small_url_encode(&format!("{:#}", i)); + let generated = format!("{}{}", + encoded, + if is_negative_impl { "!" } else { "" }, + out); + if links.insert(generated.clone()) { + Some(generated) + } else { + None + } + } else { + None + } + }) + .collect::() }; let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = v From fc284c1eee0180903fe11463dcee06e414202cf7 Mon Sep 17 00:00:00 2001 From: Dan Aloni Date: Mon, 19 Nov 2018 16:32:18 +0200 Subject: [PATCH 0130/1984] Stabilize macro_literal_matcher --- .../macro-literal-matcher.md | 17 ---------- src/libsyntax/ext/tt/macro_rules.rs | 31 ++++++++----------- src/libsyntax/feature_gate.rs | 8 ++--- src/test/run-pass/issues/issue-52169.rs | 2 +- src/test/run-pass/macros/macro-literal.rs | 2 +- .../feature-gate-macro-literal-matcher.rs | 19 ------------ .../feature-gate-macro-literal-matcher.stderr | 11 ------- 7 files changed, 17 insertions(+), 73 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/macro-literal-matcher.md delete mode 100644 src/test/ui/feature-gates/feature-gate-macro-literal-matcher.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-macro-literal-matcher.stderr diff --git a/src/doc/unstable-book/src/language-features/macro-literal-matcher.md b/src/doc/unstable-book/src/language-features/macro-literal-matcher.md deleted file mode 100644 index 870158200de..00000000000 --- a/src/doc/unstable-book/src/language-features/macro-literal-matcher.md +++ /dev/null @@ -1,17 +0,0 @@ -# `macro_literal_matcher` - -The tracking issue for this feature is: [#35625] - -The RFC is: [rfc#1576]. - -With this feature gate enabled, the [list of designators] gains one more entry: - -* `literal`: a literal. Examples: 2, "string", 'c' - -A `literal` may be followed by anything, similarly to the `ident` specifier. - -[rfc#1576]: http://rust-lang.github.io/rfcs/1576-macros-literal-matcher.html -[#35625]: https://github.com/rust-lang/rust/issues/35625 -[list of designators]: ../reference/macros-by-example.html - ------------------------- diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 6bba891278a..55c1904bd27 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -19,7 +19,7 @@ use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal}; use ext::tt::macro_parser::{parse, parse_failure_msg}; use ext::tt::quoted; use ext::tt::transcribe::transcribe; -use feature_gate::{self, emit_feature_err, Features, GateIssue}; +use feature_gate::Features; use parse::{Directory, ParseSess}; use parse::parser::Parser; use parse::token::{self, NtTT}; @@ -1027,26 +1027,21 @@ fn has_legal_fragment_specifier(sess: &ParseSess, Ok(()) } -fn is_legal_fragment_specifier(sess: &ParseSess, - features: &Features, - attrs: &[ast::Attribute], +fn is_legal_fragment_specifier(_sess: &ParseSess, + _features: &Features, + _attrs: &[ast::Attribute], frag_name: &str, - frag_span: Span) -> bool { + _frag_span: Span) -> bool { + /* + * If new fragmnet specifiers are invented in nightly, `_sess`, + * `_features`, `_attrs`, and `_frag_span` will be useful for + * here for checking against feature gates. See past versions of + * this function. + */ match frag_name { "item" | "block" | "stmt" | "expr" | "pat" | "lifetime" | - "path" | "ty" | "ident" | "meta" | "tt" | "vis" | "" => true, - "literal" => { - if !features.macro_literal_matcher && - !attr::contains_name(attrs, "allow_internal_unstable") { - let explain = feature_gate::EXPLAIN_LITERAL_MATCHER; - emit_feature_err(sess, - "macro_literal_matcher", - frag_span, - GateIssue::Language, - explain); - } - true - }, + "path" | "ty" | "ident" | "meta" | "tt" | "vis" | "literal" | + "" => true, _ => false, } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 2f5db9bd081..73567765a04 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -436,9 +436,6 @@ declare_features! ( // Allows irrefutable patterns in if-let and while-let statements (RFC 2086) (active, irrefutable_let_patterns, "1.27.0", Some(44495), None), - // Allows use of the :literal macro fragment specifier (RFC 1576) - (active, macro_literal_matcher, "1.27.0", Some(35625), None), - // inconsistent bounds in where clauses (active, trivial_bounds, "1.28.0", Some(48214), None), @@ -690,6 +687,8 @@ declare_features! ( (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), // `extern crate foo as bar;` puts `bar` into extern prelude. (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), + // Allows use of the :literal macro fragment specifier (RFC 1576) + (accepted, macro_literal_matcher, "1.31.0", Some(35625), None), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -1425,9 +1424,6 @@ pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str = pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str = "attributes of the form `#[derive_*]` are reserved for the compiler"; -pub const EXPLAIN_LITERAL_MATCHER: &'static str = - ":literal fragment specifier is experimental and subject to change"; - pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = "unsized tuple coercion is not stable enough for use and is subject to change"; diff --git a/src/test/run-pass/issues/issue-52169.rs b/src/test/run-pass/issues/issue-52169.rs index 19c0f51d235..9421dfc7897 100644 --- a/src/test/run-pass/issues/issue-52169.rs +++ b/src/test/run-pass/issues/issue-52169.rs @@ -9,7 +9,7 @@ // except according to those terms. // run-pass -#![feature(macro_literal_matcher)] +#![cfg_attr(stage0, feature(macro_literal_matcher))] macro_rules! a { ($i:literal) => { "right" }; diff --git a/src/test/run-pass/macros/macro-literal.rs b/src/test/run-pass/macros/macro-literal.rs index ecbb47757d1..07e27d9f516 100644 --- a/src/test/run-pass/macros/macro-literal.rs +++ b/src/test/run-pass/macros/macro-literal.rs @@ -9,7 +9,7 @@ // except according to those terms. // run-pass -#![feature(macro_literal_matcher)] +#![cfg_attr(stage0, feature(macro_literal_matcher))] macro_rules! mtester { ($l:literal) => { diff --git a/src/test/ui/feature-gates/feature-gate-macro-literal-matcher.rs b/src/test/ui/feature-gates/feature-gate-macro-literal-matcher.rs deleted file mode 100644 index db5cca193ab..00000000000 --- a/src/test/ui/feature-gates/feature-gate-macro-literal-matcher.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2018 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. - -// Test that the :lifetime macro fragment cannot be used when macro_lifetime_matcher -// feature gate is not used. - -macro_rules! m { ($lt:literal) => {} } -//~^ ERROR :literal fragment specifier is experimental and subject to change - -fn main() { - m!("some string literal"); -} diff --git a/src/test/ui/feature-gates/feature-gate-macro-literal-matcher.stderr b/src/test/ui/feature-gates/feature-gate-macro-literal-matcher.stderr deleted file mode 100644 index f714b916966..00000000000 --- a/src/test/ui/feature-gates/feature-gate-macro-literal-matcher.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: :literal fragment specifier is experimental and subject to change (see issue #35625) - --> $DIR/feature-gate-macro-literal-matcher.rs:14:19 - | -LL | macro_rules! m { ($lt:literal) => {} } - | ^^^^^^^^^^^ - | - = help: add #![feature(macro_literal_matcher)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. From b8ae7b801bf1f3d298493b2e7e1328a1a7ecace7 Mon Sep 17 00:00:00 2001 From: Dan Aloni Date: Tue, 20 Nov 2018 09:11:12 +0200 Subject: [PATCH 0131/1984] macro_literal_matcher: fixes per petrochenkov's review --- src/libsyntax/ext/tt/macro_rules.rs | 6 +++--- src/test/run-pass/issues/issue-52169.rs | 1 - src/test/run-pass/macros/macro-literal.rs | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 55c1904bd27..d526e464ba4 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -1033,9 +1033,9 @@ fn is_legal_fragment_specifier(_sess: &ParseSess, frag_name: &str, _frag_span: Span) -> bool { /* - * If new fragmnet specifiers are invented in nightly, `_sess`, - * `_features`, `_attrs`, and `_frag_span` will be useful for - * here for checking against feature gates. See past versions of + * If new fragment specifiers are invented in nightly, `_sess`, + * `_features`, `_attrs`, and `_frag_span` will be useful here + * for checking against feature gates. See past versions of * this function. */ match frag_name { diff --git a/src/test/run-pass/issues/issue-52169.rs b/src/test/run-pass/issues/issue-52169.rs index 9421dfc7897..c4ed534cc20 100644 --- a/src/test/run-pass/issues/issue-52169.rs +++ b/src/test/run-pass/issues/issue-52169.rs @@ -9,7 +9,6 @@ // except according to those terms. // run-pass -#![cfg_attr(stage0, feature(macro_literal_matcher))] macro_rules! a { ($i:literal) => { "right" }; diff --git a/src/test/run-pass/macros/macro-literal.rs b/src/test/run-pass/macros/macro-literal.rs index 07e27d9f516..de268e3388a 100644 --- a/src/test/run-pass/macros/macro-literal.rs +++ b/src/test/run-pass/macros/macro-literal.rs @@ -9,7 +9,6 @@ // except according to those terms. // run-pass -#![cfg_attr(stage0, feature(macro_literal_matcher))] macro_rules! mtester { ($l:literal) => { From 4687eebc287e6f715b237dbb15f6c734715b474a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 21 Nov 2018 15:34:11 -0500 Subject: [PATCH 0132/1984] preserve the original visibility for the "list stem" node Without this, the `vis` does not wind up in the tree anywhere, and then we get ICEs because the node-ids it refers to are not present. The motivation seemed to be documentation, but `ListStem` HIR nodes are ignored in rustdoc, from what I can tell. --- src/librustc/hir/lowering.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 79d605c0035..eec9d084d7e 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3139,12 +3139,8 @@ impl<'a> LoweringContext<'a> { }); } - // Privatize the degenerate import base, used only to check - // the stability of `use a::{};`, to avoid it showing up as - // a re-export by accident when `pub`, e.g. in documentation. let def = self.expect_full_def_from_use(id).next().unwrap_or(Def::Err); let path = P(self.lower_path_extra(def, &prefix, ParamMode::Explicit, None)); - *vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited); hir::ItemKind::Use(path, hir::UseKind::ListStem) } } From 2bd2fc9418ee986fd96c32308dc2ef0efcc7973d Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 21 Nov 2018 14:20:03 -0500 Subject: [PATCH 0133/1984] add regression test --- src/test/ui/issues/issue-56128.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/test/ui/issues/issue-56128.rs diff --git a/src/test/ui/issues/issue-56128.rs b/src/test/ui/issues/issue-56128.rs new file mode 100644 index 00000000000..4d36fec9c04 --- /dev/null +++ b/src/test/ui/issues/issue-56128.rs @@ -0,0 +1,13 @@ +// Regression test for #56128. When this `pub(super) use...` gets +// exploded in the HIR, we were not handling ids correctly. + +mod bar { + pub(super) use self::baz::{x, y}; + + mod baz { + pub fn x() { } + pub fn y() { } + } +} + +fn main() { } From 4c7ce7c8973ff8f4b9427faffff3ceda8a1ab7f2 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 21 Nov 2018 14:24:36 -0500 Subject: [PATCH 0134/1984] pass vis by shared reference We are not mutating it now. --- src/librustc/hir/lowering.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index eec9d084d7e..5b38263f90f 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2752,7 +2752,7 @@ impl<'a> LoweringContext<'a> { id: NodeId, name: &mut Name, attrs: &hir::HirVec, - vis: &mut hir::Visibility, + vis: &hir::Visibility, i: &ItemKind, ) -> hir::ItemKind { match *i { @@ -2955,7 +2955,7 @@ impl<'a> LoweringContext<'a> { tree: &UseTree, prefix: &Path, id: NodeId, - vis: &mut hir::Visibility, + vis: &hir::Visibility, name: &mut Name, attrs: &hir::HirVec, ) -> hir::ItemKind { @@ -3086,7 +3086,7 @@ impl<'a> LoweringContext<'a> { hir_id: new_hir_id, } = self.lower_node_id(id); - let mut vis = vis.clone(); + let vis = vis.clone(); let mut name = name.clone(); let mut prefix = prefix.clone(); @@ -3104,7 +3104,7 @@ impl<'a> LoweringContext<'a> { let item = this.lower_use_tree(use_tree, &prefix, new_id, - &mut vis, + &vis, &mut name, attrs); @@ -3384,7 +3384,7 @@ impl<'a> LoweringContext<'a> { pub fn lower_item(&mut self, i: &Item) -> Option { let mut name = i.ident.name; - let mut vis = self.lower_visibility(&i.vis, None); + let vis = self.lower_visibility(&i.vis, None); let attrs = self.lower_attrs(&i.attrs); if let ItemKind::MacroDef(ref def) = i.node { if !def.legacy || attr::contains_name(&i.attrs, "macro_export") || @@ -3403,7 +3403,7 @@ impl<'a> LoweringContext<'a> { return None; } - let node = self.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node); + let node = self.lower_item_kind(i.id, &mut name, &attrs, &vis, &i.node); let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id); From d4ee1c93ff25a7fa6f5e35dc774a648a7e6d578e Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 21 Nov 2018 11:35:49 -0700 Subject: [PATCH 0135/1984] Fix BTreeSet and BTreeMap gdb pretty-printers The BTreeSet and BTreeMap gdb pretty-printers did not take the node structure into account, and consequently only worked for shallow sets. This fixes the problem by iterating over child nodes when needed. This patch avoids the current approach of implementing some of the value manipulations in debugger-indepdendent code. This was done for convenience: a type lookup was needed for the first time, and there currently are no lldb formatters for these types. Closes #55771 --- src/etc/debugger_pretty_printers_common.py | 26 -------- src/etc/gdb_rust_pretty_printing.py | 70 ++++++++++++-------- src/test/debuginfo/pretty-std-collections.rs | 17 ++--- 3 files changed, 50 insertions(+), 63 deletions(-) diff --git a/src/etc/debugger_pretty_printers_common.py b/src/etc/debugger_pretty_printers_common.py index 1797f6708ac..b99e401929e 100644 --- a/src/etc/debugger_pretty_printers_common.py +++ b/src/etc/debugger_pretty_printers_common.py @@ -375,32 +375,6 @@ def extract_tail_head_ptr_and_cap_from_std_vecdeque(vec_val): assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR return (tail, head, data_ptr, capacity) - -def extract_length_and_ptr_from_std_btreeset(vec_val): - assert vec_val.type.get_type_kind() == TYPE_KIND_STD_BTREESET - map = vec_val.get_child_at_index(0) - root = map.get_child_at_index(0) - length = map.get_child_at_index(1).as_integer() - node = root.get_child_at_index(0) - ptr = node.get_child_at_index(0) - unique_ptr_val = ptr.get_child_at_index(0) - data_ptr = unique_ptr_val.get_child_at_index(0) - assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR - return (length, data_ptr) - - -def extract_length_and_ptr_from_std_btreemap(vec_val): - assert vec_val.type.get_type_kind() == TYPE_KIND_STD_BTREEMAP - root = vec_val.get_child_at_index(0) - length = vec_val.get_child_at_index(1).as_integer() - node = root.get_child_at_index(0) - ptr = node.get_child_at_index(0) - unique_ptr_val = ptr.get_child_at_index(0) - data_ptr = unique_ptr_val.get_child_at_index(0) - assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR - return (length, data_ptr) - - def extract_length_and_ptr_from_slice(slice_val): assert (slice_val.type.get_type_kind() == TYPE_KIND_SLICE or slice_val.type.get_type_kind() == TYPE_KIND_STR_SLICE) diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index e6d5ef1a23f..11e46e8c54c 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -304,6 +304,32 @@ def children(self): yield (str(index), (gdb_ptr + index).dereference()) +# Yield each key (and optionally value) from a BoxedNode. +def children_of_node(boxed_node, height, want_values): + ptr = boxed_node['ptr']['pointer'] + # This is written oddly because we don't want to rely on the field name being `__0`. + node_ptr = ptr[ptr.type.fields()[0]] + if height > 0: + type_name = str(node_ptr.type.target()).replace('LeafNode', 'InternalNode') + node_type = gdb.lookup_type(type_name) + node_ptr = node_ptr.cast(node_type.pointer()) + leaf = node_ptr['data'] + else: + leaf = node_ptr.dereference() + keys = leaf['keys']['value']['value'] + if want_values: + values = leaf['vals']['value']['value'] + length = int(leaf['len']) + for i in xrange(0, length + 1): + if height > 0: + for child in children_of_node(node_ptr['edges'][i], height - 1, want_values): + yield child + if i < length: + if want_values: + yield (keys[i], values[i]) + else: + yield keys[i] + class RustStdBTreeSetPrinter(object): def __init__(self, val): self.__val = val @@ -313,21 +339,16 @@ def display_hint(): return "array" def to_string(self): - (length, data_ptr) = \ - rustpp.extract_length_and_ptr_from_std_btreeset(self.__val) return (self.__val.type.get_unqualified_type_name() + - ("(len: %i)" % length)) + ("(len: %i)" % self.__val.get_wrapped_value()['map']['length'])) def children(self): - (length, data_ptr) = \ - rustpp.extract_length_and_ptr_from_std_btreeset(self.__val) - leaf_node = GdbValue(data_ptr.get_wrapped_value().dereference()) - maybe_uninit_keys = leaf_node.get_child_at_index(3) - manually_drop_keys = maybe_uninit_keys.get_child_at_index(1) - keys = manually_drop_keys.get_child_at_index(0) - gdb_ptr = keys.get_wrapped_value() - for index in xrange(length): - yield (str(index), gdb_ptr[index]) + root = self.__val.get_wrapped_value()['map']['root'] + node_ptr = root['node'] + i = 0 + for child in children_of_node(node_ptr, root['height'], False): + yield (str(i), child) + i = i + 1 class RustStdBTreeMapPrinter(object): @@ -339,26 +360,17 @@ def display_hint(): return "map" def to_string(self): - (length, data_ptr) = \ - rustpp.extract_length_and_ptr_from_std_btreemap(self.__val) return (self.__val.type.get_unqualified_type_name() + - ("(len: %i)" % length)) + ("(len: %i)" % self.__val.get_wrapped_value()['length'])) def children(self): - (length, data_ptr) = \ - rustpp.extract_length_and_ptr_from_std_btreemap(self.__val) - leaf_node = GdbValue(data_ptr.get_wrapped_value().dereference()) - maybe_uninit_keys = leaf_node.get_child_at_index(3) - manually_drop_keys = maybe_uninit_keys.get_child_at_index(1) - keys = manually_drop_keys.get_child_at_index(0) - keys_ptr = keys.get_wrapped_value() - maybe_uninit_vals = leaf_node.get_child_at_index(4) - manually_drop_vals = maybe_uninit_vals.get_child_at_index(1) - vals = manually_drop_vals.get_child_at_index(0) - vals_ptr = vals.get_wrapped_value() - for index in xrange(length): - yield (str(index), keys_ptr[index]) - yield (str(index), vals_ptr[index]) + root = self.__val.get_wrapped_value()['root'] + node_ptr = root['node'] + i = 0 + for child in children_of_node(node_ptr, root['height'], True): + yield (str(i), child[0]) + yield (str(i), child[1]) + i = i + 1 class RustStdStringPrinter(object): diff --git a/src/test/debuginfo/pretty-std-collections.rs b/src/test/debuginfo/pretty-std-collections.rs index 8e37a884b34..55e20d67276 100644 --- a/src/test/debuginfo/pretty-std-collections.rs +++ b/src/test/debuginfo/pretty-std-collections.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength // ignore-windows failing on win32 bot // ignore-freebsd: gdb package too new // ignore-android: FIXME(#10381) @@ -20,10 +21,10 @@ // gdb-command: run // gdb-command: print btree_set -// gdb-check:$1 = BTreeSet(len: 3) = {3, 5, 7} +// gdb-check:$1 = BTreeSet(len: 15) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} // gdb-command: print btree_map -// gdb-check:$2 = BTreeMap(len: 3) = {[3] = 3, [5] = 7, [7] = 4} +// gdb-check:$2 = BTreeMap(len: 15) = {[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} // gdb-command: print vec_deque // gdb-check:$3 = VecDeque(len: 3, cap: 8) = {5, 3, 7} @@ -38,15 +39,15 @@ fn main() { // BTreeSet let mut btree_set = BTreeSet::new(); - btree_set.insert(5); - btree_set.insert(3); - btree_set.insert(7); + for i in 0..15 { + btree_set.insert(i); + } // BTreeMap let mut btree_map = BTreeMap::new(); - btree_map.insert(5, 7); - btree_map.insert(3, 3); - btree_map.insert(7, 4); + for i in 0..15 { + btree_map.insert(i, i); + } // VecDeque let mut vec_deque = VecDeque::new(); From 9cdf4911db1b143f0e40913793389c72e4fa6b17 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 21 Nov 2018 16:09:17 -0500 Subject: [PATCH 0136/1984] hack: ignore list-stems for pub lint --- src/librustc_lint/builtin.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 7dd1ca3493e..0348ba1f1af 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1136,7 +1136,15 @@ impl UnreachablePub { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub { fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { - self.perform_lint(cx, "item", item.id, &item.vis, item.span, true); + match item.node { + hir::ItemKind::Use(_, hir::UseKind::ListStem) => { + // Hack: ignore these `use foo::{}` remnants which are just a figment + // our IR. + } + _ => { + self.perform_lint(cx, "item", item.id, &item.vis, item.span, true); + } + } } fn check_foreign_item(&mut self, cx: &LateContext, foreign_item: &hir::ForeignItem) { From 1dc11249792aca93ee0bd6ff44fe9084adf78ddc Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 22 Nov 2018 01:13:09 +0300 Subject: [PATCH 0137/1984] resolve: Fix some asserts in import validation --- src/librustc_resolve/resolve_imports.rs | 6 ++- src/test/ui/imports/auxiliary/issue-56125.rs | 9 ++++ src/test/ui/imports/issue-56125.rs | 12 +++++ src/test/ui/imports/issue-56125.stderr | 46 ++++++++++++++++++++ 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/imports/auxiliary/issue-56125.rs create mode 100644 src/test/ui/imports/issue-56125.rs create mode 100644 src/test/ui/imports/issue-56125.stderr diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index dfc066e4b96..616cc9d2fc5 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -842,12 +842,14 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { module } PathResult::Failed(span, msg, false) => { - assert!(directive.imported_module.get().is_none()); + assert!(!self.ambiguity_errors.is_empty() || + directive.imported_module.get().is_none()); resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); return None; } PathResult::Failed(span, msg, true) => { - assert!(directive.imported_module.get().is_none()); + assert!(!self.ambiguity_errors.is_empty() || + directive.imported_module.get().is_none()); return if let Some((suggested_path, note)) = self.make_path_suggestion( span, directive.module_path.clone(), &directive.parent_scope ) { diff --git a/src/test/ui/imports/auxiliary/issue-56125.rs b/src/test/ui/imports/auxiliary/issue-56125.rs new file mode 100644 index 00000000000..0ff407756b3 --- /dev/null +++ b/src/test/ui/imports/auxiliary/issue-56125.rs @@ -0,0 +1,9 @@ +pub mod last_segment { + pub mod issue_56125 {} +} + +pub mod non_last_segment { + pub mod non_last_segment { + pub mod issue_56125 {} + } +} diff --git a/src/test/ui/imports/issue-56125.rs b/src/test/ui/imports/issue-56125.rs new file mode 100644 index 00000000000..4baeb8a34dd --- /dev/null +++ b/src/test/ui/imports/issue-56125.rs @@ -0,0 +1,12 @@ +// edition:2018 +// compile-flags:--extern issue_56125 +// aux-build:issue-56125.rs + +use issue_56125::last_segment::*; +//~^ ERROR `issue_56125` is ambiguous +//~| ERROR unresolved import `issue_56125::last_segment` +use issue_56125::non_last_segment::non_last_segment::*; +//~^ ERROR `issue_56125` is ambiguous +//~| ERROR failed to resolve: could not find `non_last_segment` in `issue_56125` + +fn main() {} diff --git a/src/test/ui/imports/issue-56125.stderr b/src/test/ui/imports/issue-56125.stderr new file mode 100644 index 00000000000..096d5be97f0 --- /dev/null +++ b/src/test/ui/imports/issue-56125.stderr @@ -0,0 +1,46 @@ +error[E0433]: failed to resolve: could not find `non_last_segment` in `issue_56125` + --> $DIR/issue-56125.rs:8:18 + | +LL | use issue_56125::non_last_segment::non_last_segment::*; + | ^^^^^^^^^^^^^^^^ could not find `non_last_segment` in `issue_56125` + +error[E0432]: unresolved import `issue_56125::last_segment` + --> $DIR/issue-56125.rs:5:18 + | +LL | use issue_56125::last_segment::*; + | ^^^^^^^^^^^^ could not find `last_segment` in `issue_56125` + +error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution) + --> $DIR/issue-56125.rs:5:5 + | +LL | use issue_56125::last_segment::*; + | ^^^^^^^^^^^ ambiguous name + | + = note: `issue_56125` could refer to an extern crate passed with `--extern` + = help: use `::issue_56125` to refer to this extern crate unambiguously +note: `issue_56125` could also refer to the module imported here + --> $DIR/issue-56125.rs:5:5 + | +LL | use issue_56125::last_segment::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `self::issue_56125` to refer to this module unambiguously + +error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution) + --> $DIR/issue-56125.rs:8:5 + | +LL | use issue_56125::non_last_segment::non_last_segment::*; + | ^^^^^^^^^^^ ambiguous name + | + = note: `issue_56125` could refer to an extern crate passed with `--extern` + = help: use `::issue_56125` to refer to this extern crate unambiguously +note: `issue_56125` could also refer to the module imported here + --> $DIR/issue-56125.rs:5:5 + | +LL | use issue_56125::last_segment::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `self::issue_56125` to refer to this module unambiguously + +error: aborting due to 4 previous errors + +Some errors occurred: E0432, E0433, E0659. +For more information about an error, try `rustc --explain E0432`. From c746ecfa0190548f78afe62d4d8e4140ac4e4621 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 21 Nov 2018 23:21:50 +0100 Subject: [PATCH 0138/1984] Add test for sidebar link generation --- src/test/rustdoc/sidebar-link-generation.rs | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/test/rustdoc/sidebar-link-generation.rs diff --git a/src/test/rustdoc/sidebar-link-generation.rs b/src/test/rustdoc/sidebar-link-generation.rs new file mode 100644 index 00000000000..2482a7e82b9 --- /dev/null +++ b/src/test/rustdoc/sidebar-link-generation.rs @@ -0,0 +1,23 @@ +// Copyright 2014 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. + +#![crate_name = "foo"] + +// @has foo/struct.SomeStruct.html '//*[@class="sidebar-links"]/a[@href="#method.some_fn-1"]' \ +// "some_fn" +pub struct SomeStruct { _inner: T } + +impl SomeStruct<()> { + pub fn some_fn(&self) {} +} + +impl SomeStruct { + pub fn some_fn(&self) {} +} From ebf3c8d8e993ea0ef94c9ff9bf33436c6a526e19 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 21 Nov 2018 18:50:10 -0500 Subject: [PATCH 0139/1984] add compile-pass annotation --- src/test/ui/issues/issue-56128.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/ui/issues/issue-56128.rs b/src/test/ui/issues/issue-56128.rs index 4d36fec9c04..3a3eccdc33c 100644 --- a/src/test/ui/issues/issue-56128.rs +++ b/src/test/ui/issues/issue-56128.rs @@ -1,5 +1,7 @@ // Regression test for #56128. When this `pub(super) use...` gets // exploded in the HIR, we were not handling ids correctly. +// +// compile-pass mod bar { pub(super) use self::baz::{x, y}; From ec3ac112e115c02a942c7a84c37a0cfd270dbad4 Mon Sep 17 00:00:00 2001 From: ariasuni Date: Wed, 21 Nov 2018 23:39:33 +0100 Subject: [PATCH 0140/1984] Make std::os::unix/linux::fs::MetadataExt::a/m/ctime* documentation clearer --- src/libstd/os/linux/fs.rs | 18 ++++++++++++------ src/libstd/sys/unix/ext/fs.rs | 18 ++++++++++++------ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/libstd/os/linux/fs.rs b/src/libstd/os/linux/fs.rs index 76fb10da850..b518f524e0b 100644 --- a/src/libstd/os/linux/fs.rs +++ b/src/libstd/os/linux/fs.rs @@ -191,7 +191,7 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_size(&self) -> u64; - /// Returns the last access time. + /// Returns the last access time of the file, in seconds since Unix Epoch. /// /// # Examples /// @@ -208,7 +208,9 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_atime(&self) -> i64; - /// Returns the last access time, nano seconds part. + /// Returns the last access time of the file, in nanoseconds since [`st_atime`]. + /// + /// [`st_atime`]: #tymethod.st_atime /// /// # Examples /// @@ -225,7 +227,7 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_atime_nsec(&self) -> i64; - /// Returns the last modification time. + /// Returns the last modification time of the file, in seconds since Unix Epoch. /// /// # Examples /// @@ -242,7 +244,9 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_mtime(&self) -> i64; - /// Returns the last modification time, nano seconds part. + /// Returns the last modification time of the file, in nanoseconds since [`st_mtime`]. + /// + /// [`st_mtime`]: #tymethod.st_mtime /// /// # Examples /// @@ -259,7 +263,7 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_mtime_nsec(&self) -> i64; - /// Returns the last status change time. + /// Returns the last status change time of the file, in seconds since Unix Epoch. /// /// # Examples /// @@ -276,7 +280,9 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_ctime(&self) -> i64; - /// Returns the last status change time, nano seconds part. + /// Returns the last status change time of the file, in nanoseconds since [`st_ctime`]. + /// + /// [`st_ctime`]: #tymethod.st_ctime /// /// # Examples /// diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 507e9d88171..7e65bbdef2a 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -522,7 +522,7 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn size(&self) -> u64; - /// Returns the time of the last access to the file. + /// Returns the last access time of the file, in seconds since Unix Epoch. /// /// # Examples /// @@ -539,7 +539,9 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn atime(&self) -> i64; - /// Returns the time of the last access to the file in nanoseconds. + /// Returns the last access time of the file, in nanoseconds since [`atime`]. + /// + /// [`atime`]: #tymethod.atime /// /// # Examples /// @@ -556,7 +558,7 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn atime_nsec(&self) -> i64; - /// Returns the time of the last modification of the file. + /// Returns the last modification time of the file, in seconds since Unix Epoch. /// /// # Examples /// @@ -573,7 +575,9 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn mtime(&self) -> i64; - /// Returns the time of the last modification of the file in nanoseconds. + /// Returns the last modification time of the file, in nanoseconds since [`mtime`]. + /// + /// [`mtime`]: #tymethod.mtime /// /// # Examples /// @@ -590,7 +594,7 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn mtime_nsec(&self) -> i64; - /// Returns the time of the last status change of the file. + /// Returns the last status change time of the file, in seconds since Unix Epoch. /// /// # Examples /// @@ -607,7 +611,9 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn ctime(&self) -> i64; - /// Returns the time of the last status change of the file in nanoseconds. + /// Returns the last status change time of the file, in nanoseconds since [`ctime`]. + /// + /// [`ctime`]: #tymethod.ctime /// /// # Examples /// From d56e8920852adec249c9d8159348a94dcafbd31c Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 8 Sep 2018 22:14:55 +0300 Subject: [PATCH 0141/1984] rustc_target: rename abi::Align to AbiAndPrefAlign. --- src/librustc/mir/interpret/allocation.rs | 10 +- src/librustc/mir/interpret/error.rs | 8 +- src/librustc/session/code_stats.rs | 4 +- src/librustc/ty/layout.rs | 14 +-- src/librustc_codegen_llvm/builder.rs | 24 ++--- src/librustc_codegen_llvm/consts.rs | 10 +- .../debuginfo/metadata.rs | 28 +++-- src/librustc_codegen_llvm/type_of.rs | 13 +-- src/librustc_codegen_ssa/base.rs | 6 +- src/librustc_codegen_ssa/glue.rs | 22 ++-- src/librustc_codegen_ssa/meth.rs | 6 +- src/librustc_codegen_ssa/mir/operand.rs | 8 +- src/librustc_codegen_ssa/mir/place.rs | 11 +- src/librustc_codegen_ssa/mir/rvalue.rs | 8 +- src/librustc_codegen_ssa/traits/builder.rs | 27 ++--- src/librustc_codegen_ssa/traits/statics.rs | 16 ++- src/librustc_codegen_ssa/traits/type_.rs | 6 +- src/librustc_mir/interpret/eval_context.rs | 12 +-- src/librustc_mir/interpret/memory.rs | 56 +++++----- src/librustc_mir/interpret/place.rs | 18 ++-- src/librustc_mir/interpret/snapshot.rs | 4 +- src/librustc_mir/interpret/traits.rs | 6 +- src/librustc_mir/interpret/validity.rs | 6 +- src/librustc_target/abi/call/mod.rs | 10 +- src/librustc_target/abi/call/powerpc64.rs | 4 +- src/librustc_target/abi/mod.rs | 101 +++++++++--------- 26 files changed, 220 insertions(+), 218 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 02c0ebcec4f..eb44c3c8c5f 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -12,7 +12,7 @@ use super::{Pointer, EvalResult, AllocId}; -use ty::layout::{Size, Align}; +use ty::layout::{Size, AbiAndPrefAlign}; use syntax::ast::Mutability; use std::iter; use mir; @@ -40,7 +40,7 @@ pub struct Allocation { /// Denotes undefined memory. Reading from undefined memory is forbidden in miri pub undef_mask: UndefMask, /// The alignment of the allocation to detect unaligned reads. - pub align: Align, + pub align: AbiAndPrefAlign, /// Whether the allocation is mutable. /// Also used by codegen to determine if a static should be put into mutable memory, /// which happens for `static mut` and `static` with interior mutability. @@ -90,7 +90,7 @@ impl AllocationExtra<()> for () {} impl Allocation { /// Creates a read-only allocation initialized by the given bytes - pub fn from_bytes(slice: &[u8], align: Align) -> Self { + pub fn from_bytes(slice: &[u8], align: AbiAndPrefAlign) -> Self { let mut undef_mask = UndefMask::new(Size::ZERO); undef_mask.grow(Size::from_bytes(slice.len() as u64), true); Self { @@ -104,10 +104,10 @@ impl Allocation { } pub fn from_byte_aligned_bytes(slice: &[u8]) -> Self { - Allocation::from_bytes(slice, Align::from_bytes(1, 1).unwrap()) + Allocation::from_bytes(slice, AbiAndPrefAlign::from_bytes(1, 1).unwrap()) } - pub fn undef(size: Size, align: Align) -> Self { + pub fn undef(size: Size, align: AbiAndPrefAlign) -> Self { assert_eq!(size.bytes() as usize as u64, size.bytes()); Allocation { bytes: vec![0; size.bytes() as usize], diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index f1ac4b21058..bae53a9216a 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -13,7 +13,7 @@ use std::{fmt, env}; use hir::map::definitions::DefPathData; use mir; use ty::{self, Ty, layout}; -use ty::layout::{Size, Align, LayoutError}; +use ty::layout::{Size, AbiAndPrefAlign, LayoutError}; use rustc_target::spec::abi::Abi; use super::{RawConst, Pointer, InboundsCheck, ScalarMaybeUndef}; @@ -301,8 +301,8 @@ pub enum EvalErrorKind<'tcx, O> { TlsOutOfBounds, AbiViolation(String), AlignmentCheckFailed { - required: Align, - has: Align, + required: AbiAndPrefAlign, + has: AbiAndPrefAlign, }, ValidationFailure(String), CalledClosureAsFunction, @@ -315,7 +315,7 @@ pub enum EvalErrorKind<'tcx, O> { DeallocatedWrongMemoryKind(String, String), ReallocateNonBasePtr, DeallocateNonBasePtr, - IncorrectAllocationInformation(Size, Size, Align, Align), + IncorrectAllocationInformation(Size, Size, AbiAndPrefAlign, AbiAndPrefAlign), Layout(layout::LayoutError<'tcx>), HeapAllocZeroBytes, HeapAllocNonPowerOfTwoAlignment(u64), diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs index b1dcfdfcda0..34a89ccf7a2 100644 --- a/src/librustc/session/code_stats.rs +++ b/src/librustc/session/code_stats.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc_target::abi::{Align, Size}; +use rustc_target::abi::{AbiAndPrefAlign, Size}; use rustc_data_structures::fx::{FxHashSet}; use std::cmp::{self, Ordering}; @@ -63,7 +63,7 @@ impl CodeStats { pub fn record_type_size(&mut self, kind: DataTypeKind, type_desc: S, - align: Align, + align: AbiAndPrefAlign, overall_size: Size, packed: bool, opt_discr_size: Option, diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index d7fb8da7acd..76c3c467feb 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -248,7 +248,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { /// A univariant, the last field of which may be coerced to unsized. MaybeUnsized, /// A univariant, but with a prefix of an arbitrary size & alignment (e.g. enum tag). - Prefixed(Size, Align), + Prefixed(Size, AbiAndPrefAlign), } let univariant_uninterned = |fields: &[TyLayout<'_>], repr: &ReprOptions, kind| { @@ -259,7 +259,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let pack = { let pack = repr.pack as u64; - Align::from_bytes(pack, pack).unwrap() + AbiAndPrefAlign::from_bytes(pack, pack).unwrap() }; let mut align = if packed { @@ -352,7 +352,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { if repr.align > 0 { let repr_align = repr.align as u64; - align = align.max(Align::from_bytes(repr_align, repr_align).unwrap()); + align = align.max(AbiAndPrefAlign::from_bytes(repr_align, repr_align).unwrap()); debug!("univariant repr_align: {:?}", repr_align); } @@ -682,7 +682,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let pack = { let pack = def.repr.pack as u64; - Align::from_bytes(pack, pack).unwrap() + AbiAndPrefAlign::from_bytes(pack, pack).unwrap() }; let mut align = if packed { @@ -694,7 +694,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { if def.repr.align > 0 { let repr_align = def.repr.align as u64; align = align.max( - Align::from_bytes(repr_align, repr_align).unwrap()); + AbiAndPrefAlign::from_bytes(repr_align, repr_align).unwrap()); } let optimize = !def.repr.inhibit_union_abi_opt(); @@ -964,7 +964,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let mut size = Size::ZERO; // We're interested in the smallest alignment, so start large. - let mut start_align = Align::from_bytes(256, 256).unwrap(); + let mut start_align = AbiAndPrefAlign::from_bytes(256, 256).unwrap(); assert_eq!(Integer::for_abi_align(dl, start_align), None); // repr(C) on an enum tells us to make a (tag, union) layout, @@ -1994,7 +1994,7 @@ impl_stable_hash_for!(enum ::ty::layout::Primitive { Pointer }); -impl<'gcx> HashStable> for Align { +impl<'gcx> HashStable> for AbiAndPrefAlign { fn hash_stable(&self, hcx: &mut StableHashingContext<'gcx>, hasher: &mut StableHasher) { diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 34e4f4d7e18..38400946a91 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -19,7 +19,7 @@ use type_of::LayoutLlvmExt; use value::Value; use libc::{c_uint, c_char}; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::{self, Align, Size, TyLayout}; +use rustc::ty::layout::{self, AbiAndPrefAlign, Size, TyLayout}; use rustc::session::config; use rustc_data_structures::small_c_str::SmallCStr; use rustc_codegen_ssa::traits::*; @@ -457,7 +457,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { + fn alloca(&mut self, ty: &'ll Type, name: &str, align: AbiAndPrefAlign) -> &'ll Value { let mut bx = Builder::with_cx(self.cx); bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) @@ -465,7 +465,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { bx.dynamic_alloca(ty, name, align) } - fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { + fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: AbiAndPrefAlign) -> &'ll Value { self.count_insn("alloca"); unsafe { let alloca = if name.is_empty() { @@ -484,7 +484,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ty: &'ll Type, len: &'ll Value, name: &str, - align: Align) -> &'ll Value { + align: AbiAndPrefAlign) -> &'ll Value { self.count_insn("alloca"); unsafe { let alloca = if name.is_empty() { @@ -499,7 +499,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value { + fn load(&mut self, ptr: &'ll Value, align: AbiAndPrefAlign) -> &'ll Value { self.count_insn("load"); unsafe { let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); @@ -639,7 +639,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn store(&mut self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value { + fn store(&mut self, val: &'ll Value, ptr: &'ll Value, align: AbiAndPrefAlign) -> &'ll Value { self.store_with_flags(val, ptr, align, MemFlags::empty()) } @@ -647,7 +647,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { &mut self, val: &'ll Value, ptr: &'ll Value, - align: Align, + align: AbiAndPrefAlign, flags: MemFlags, ) -> &'ll Value { debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags); @@ -878,8 +878,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn memcpy(&mut self, dst: &'ll Value, dst_align: Align, - src: &'ll Value, src_align: Align, + fn memcpy(&mut self, dst: &'ll Value, dst_align: AbiAndPrefAlign, + src: &'ll Value, src_align: AbiAndPrefAlign, size: &'ll Value, flags: MemFlags) { if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memcpy. @@ -898,8 +898,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn memmove(&mut self, dst: &'ll Value, dst_align: Align, - src: &'ll Value, src_align: Align, + fn memmove(&mut self, dst: &'ll Value, dst_align: AbiAndPrefAlign, + src: &'ll Value, src_align: AbiAndPrefAlign, size: &'ll Value, flags: MemFlags) { if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memmove. @@ -923,7 +923,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ptr: &'ll Value, fill_byte: &'ll Value, size: &'ll Value, - align: Align, + align: AbiAndPrefAlign, flags: MemFlags, ) { let ptr_width = &self.cx().sess().target.target.target_pointer_width; diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 821ac931aac..158bc6eb9c1 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -28,7 +28,7 @@ use value::Value; use rustc::ty::{self, Ty}; use rustc_codegen_ssa::traits::*; -use rustc::ty::layout::{self, Size, Align, LayoutOf}; +use rustc::ty::layout::{self, Size, AbiAndPrefAlign, LayoutOf}; use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags}; @@ -89,12 +89,12 @@ pub fn codegen_static_initializer( fn set_global_alignment(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, - mut align: Align) { + mut align: AbiAndPrefAlign) { // The target may require greater alignment for globals than the type does. // Note: GCC and Clang also allow `__attribute__((aligned))` on variables, // which can force it to be smaller. Rust doesn't support this yet. if let Some(min) = cx.sess().target.target.options.min_global_align { - match ty::layout::Align::from_bits(min, min) { + match ty::layout::AbiAndPrefAlign::from_bits(min, min) { Ok(min) => align = align.max(min), Err(err) => { cx.sess().err(&format!("invalid minimum global alignment: {}", err)); @@ -186,7 +186,7 @@ impl StaticMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn static_addr_of_mut( &self, cv: &'ll Value, - align: Align, + align: AbiAndPrefAlign, kind: Option<&str>, ) -> &'ll Value { unsafe { @@ -212,7 +212,7 @@ impl StaticMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn static_addr_of( &self, cv: &'ll Value, - align: Align, + align: AbiAndPrefAlign, kind: Option<&str>, ) -> &'ll Value { if let Some(&gv) = self.const_globals.borrow().get(&cv) { diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 1c787a96932..42b48b728fd 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -35,7 +35,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc::ty::Instance; use common::CodegenCx; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; -use rustc::ty::layout::{self, Align, HasDataLayout, Integer, IntegerExt, LayoutOf, +use rustc::ty::layout::{self, AbiAndPrefAlign, HasDataLayout, Integer, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout}; use rustc::session::config; use rustc::util::nodemap::FxHashMap; @@ -923,7 +923,7 @@ struct MemberDescription<'ll> { type_metadata: &'ll DIType, offset: Size, size: Size, - align: Align, + align: AbiAndPrefAlign, flags: DIFlags, discriminant: Option, } @@ -985,13 +985,12 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> { f.ident.to_string() }; let field = layout.field(cx, i); - let (size, align) = field.size_and_align(); MemberDescription { name, type_metadata: type_metadata(cx, field.ty, self.span), offset: layout.fields.offset(i), - size, - align, + size: field.size, + align: field.align, flags: DIFlags::FlagZero, discriminant: None, } @@ -1109,13 +1108,12 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> { -> Vec> { self.variant.fields.iter().enumerate().map(|(i, f)| { let field = self.layout.field(cx, i); - let (size, align) = field.size_and_align(); MemberDescription { name: f.ident.to_string(), type_metadata: type_metadata(cx, field.ty, self.span), offset: Size::ZERO, - size, - align, + size: field.size, + align: field.align, flags: DIFlags::FlagZero, discriminant: None, } @@ -1587,8 +1585,6 @@ fn prepare_enum_metadata( _ => {} } - let (enum_type_size, enum_type_align) = layout.size_and_align(); - let enum_name = SmallCStr::new(&enum_name); let unique_type_id_str = SmallCStr::new( debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id) @@ -1610,8 +1606,8 @@ fn prepare_enum_metadata( enum_name.as_ptr(), file_metadata, UNKNOWN_LINE_NUMBER, - enum_type_size.bits(), - enum_type_align.abi_bits() as u32, + layout.size.bits(), + layout.align.abi_bits() as u32, DIFlags::FlagZero, None, 0, // RuntimeLang @@ -1695,8 +1691,8 @@ fn prepare_enum_metadata( ptr::null_mut(), file_metadata, UNKNOWN_LINE_NUMBER, - enum_type_size.bits(), - enum_type_align.abi_bits() as u32, + layout.size.bits(), + layout.align.abi_bits() as u32, DIFlags::FlagZero, discriminator_metadata, empty_array, @@ -1712,8 +1708,8 @@ fn prepare_enum_metadata( enum_name.as_ptr(), file_metadata, UNKNOWN_LINE_NUMBER, - enum_type_size.bits(), - enum_type_align.abi_bits() as u32, + layout.size.bits(), + layout.align.abi_bits() as u32, DIFlags::FlagZero, None, type_array, diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 90c02cddb2b..a07fa944891 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -12,7 +12,7 @@ use abi::{FnType, FnTypeExt}; use common::*; use rustc::hir; use rustc::ty::{self, Ty, TypeFoldable}; -use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout}; +use rustc::ty::layout::{self, AbiAndPrefAlign, LayoutOf, Size, TyLayout}; use rustc_target::abi::FloatTy; use rustc_mir::monomorphize::item::DefPathBasedNames; use type_::Type; @@ -80,7 +80,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, match layout.fields { layout::FieldPlacement::Union(_) => { - let fill = cx.type_padding_filler( layout.size, layout.align); + let fill = cx.type_padding_filler(layout.size, layout.align); let packed = false; match name { None => { @@ -165,7 +165,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } impl<'a, 'tcx> CodegenCx<'a, 'tcx> { - pub fn align_of(&self, ty: Ty<'tcx>) -> Align { + pub fn align_of(&self, ty: Ty<'tcx>) -> AbiAndPrefAlign { self.layout_of(ty).align } @@ -173,8 +173,9 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> { self.layout_of(ty).size } - pub fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, Align) { - self.layout_of(ty).size_and_align() + pub fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, AbiAndPrefAlign) { + let layout = self.layout_of(ty); + (layout.size, layout.align) } } @@ -196,7 +197,7 @@ pub enum PointerKind { #[derive(Copy, Clone)] pub struct PointeeInfo { pub size: Size, - pub align: Align, + pub align: AbiAndPrefAlign, pub safe: Option, } diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 856bb9533c8..e80ff8b6580 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -31,7 +31,7 @@ use rustc::middle::lang_items::StartFnLangItem; use rustc::middle::weak_lang_items; use rustc::mir::mono::{Stats, CodegenUnitNameBuilder}; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; +use rustc::ty::layout::{self, AbiAndPrefAlign, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::ty::query::Providers; use rustc::middle::cstore::{self, LinkagePreference}; use rustc::util::common::{time, print_time_passes_entry}; @@ -410,9 +410,9 @@ pub fn to_immediate_scalar<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( pub fn memcpy_ty<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, dst: Bx::Value, - dst_align: Align, + dst_align: AbiAndPrefAlign, src: Bx::Value, - src_align: Align, + src_align: AbiAndPrefAlign, layout: TyLayout<'tcx>, flags: MemFlags, ) { diff --git a/src/librustc_codegen_ssa/glue.rs b/src/librustc_codegen_ssa/glue.rs index 515f36b5c65..bf4c53f228e 100644 --- a/src/librustc_codegen_ssa/glue.rs +++ b/src/librustc_codegen_ssa/glue.rs @@ -25,14 +25,12 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( t: Ty<'tcx>, info: Option ) -> (Bx::Value, Bx::Value) { - debug!("calculate size of DST: {}; with lost info: {:?}", - t, info); - if bx.cx().type_is_sized(t) { - let (size, align) = bx.cx().layout_of(t).size_and_align(); - debug!("size_and_align_of_dst t={} info={:?} size: {:?} align: {:?}", - t, info, size, align); - let size = bx.cx().const_usize(size.bytes()); - let align = bx.cx().const_usize(align.abi()); + let layout = bx.cx().layout_of(t); + debug!("size_and_align_of_dst(ty={}, info={:?}): layout: {:?}", + t, info, layout); + if !layout.is_unsized() { + let size = bx.cx().const_usize(layout.size.bytes()); + let align = bx.cx().const_usize(layout.align.abi()); return (size, align); } match t.sty { @@ -42,19 +40,17 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( (meth::SIZE.get_usize(bx, vtable), meth::ALIGN.get_usize(bx, vtable)) } ty::Slice(_) | ty::Str => { - let unit = t.sequence_element_type(bx.tcx()); + let unit = layout.field(bx.cx(), 0); // The info in this case is the length of the str, so the size is that // times the unit size. - let (size, align) = bx.cx().layout_of(unit).size_and_align(); - (bx.mul(info.unwrap(), bx.cx().const_usize(size.bytes())), - bx.cx().const_usize(align.abi())) + (bx.mul(info.unwrap(), bx.cx().const_usize(unit.size.bytes())), + bx.cx().const_usize(unit.align.abi())) } _ => { // First get the size of all statically known fields. // Don't use size_of because it also rounds up to alignment, which we // want to avoid, as the unsized field's alignment could be smaller. assert!(!t.is_simd()); - let layout = bx.cx().layout_of(t); debug!("DST {} layout: {:?}", t, layout); let i = layout.fields.count() - 1; diff --git a/src/librustc_codegen_ssa/meth.rs b/src/librustc_codegen_ssa/meth.rs index 06c4f7a87d8..d0b8c166b12 100644 --- a/src/librustc_codegen_ssa/meth.rs +++ b/src/librustc_codegen_ssa/meth.rs @@ -100,15 +100,15 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( }) }); - let (size, align) = cx.layout_of(ty).size_and_align(); + let layout = cx.layout_of(ty); // ///////////////////////////////////////////////////////////////////////////////////////////// // If you touch this code, be sure to also make the corresponding changes to // `get_vtable` in rust_mir/interpret/traits.rs // ///////////////////////////////////////////////////////////////////////////////////////////// let components: Vec<_> = [ cx.get_fn(monomorphize::resolve_drop_in_place(cx.tcx(), ty)), - cx.const_usize(size.bytes()), - cx.const_usize(align.abi()) + cx.const_usize(layout.size.bytes()), + cx.const_usize(layout.align.abi()) ].iter().cloned().chain(methods).collect(); let vtable_const = cx.const_struct(&components, false); diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index d574d89d67e..4c92ab7eda5 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -11,7 +11,7 @@ use rustc::mir::interpret::{ConstValue, ErrorHandled}; use rustc::mir; use rustc::ty; -use rustc::ty::layout::{self, Align, LayoutOf, TyLayout}; +use rustc::ty::layout::{self, AbiAndPrefAlign, LayoutOf, TyLayout}; use base; use MemFlags; @@ -33,7 +33,7 @@ pub enum OperandValue { /// to be valid for the operand's lifetime. /// The second value, if any, is the extra data (vtable or length) /// which indicates that it refers to an unsized rvalue. - Ref(V, Option, Align), + Ref(V, Option, AbiAndPrefAlign), /// A single LLVM value. Immediate(V), /// A pair of immediate LLVM values. Used by fat pointers too. @@ -348,8 +348,8 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandValue { }; // FIXME: choose an appropriate alignment, or use dynamic align somehow - let max_align = Align::from_bits(128, 128).unwrap(); - let min_align = Align::from_bits(8, 8).unwrap(); + let max_align = AbiAndPrefAlign::from_bits(128, 128).unwrap(); + let min_align = AbiAndPrefAlign::from_bits(8, 8).unwrap(); // Allocate an appropriate region on the stack, and copy the value into it let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra)); diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 5b36ee8fd18..e6216c8724f 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -9,7 +9,7 @@ // except according to those terms. use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; +use rustc::ty::layout::{self, AbiAndPrefAlign, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::mir; use rustc::mir::tcx::PlaceTy; use MemFlags; @@ -33,14 +33,14 @@ pub struct PlaceRef<'tcx, V> { pub layout: TyLayout<'tcx>, /// What alignment we know for this place - pub align: Align, + pub align: AbiAndPrefAlign, } impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { pub fn new_sized( llval: V, layout: TyLayout<'tcx>, - align: Align, + align: AbiAndPrefAlign, ) -> PlaceRef<'tcx, V> { assert!(!layout.is_unsized()); PlaceRef { @@ -308,9 +308,8 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { // Issue #34427: As workaround for LLVM bug on ARM, // use memset of 0 before assigning niche value. let fill_byte = bx.cx().const_u8(0); - let (size, align) = self.layout.size_and_align(); - let size = bx.cx().const_usize(size.bytes()); - bx.memset(self.llval, fill_byte, size, align, MemFlags::empty()); + let size = bx.cx().const_usize(self.layout.size.bytes()); + bx.memset(self.llval, fill_byte, size, self.align, MemFlags::empty()); } let niche = self.project_field(bx, 0); diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 6b1efa060fd..167a143ec31 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -496,10 +496,10 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => { - let content_ty: Ty<'tcx> = self.monomorphize(&content_ty); - let (size, align) = bx.cx().layout_of(content_ty).size_and_align(); - let llsize = bx.cx().const_usize(size.bytes()); - let llalign = bx.cx().const_usize(align.abi()); + let content_ty = self.monomorphize(&content_ty); + let content_layout = bx.cx().layout_of(content_ty); + let llsize = bx.cx().const_usize(content_layout.size.bytes()); + let llalign = bx.cx().const_usize(content_layout.align.abi()); let box_layout = bx.cx().layout_of(bx.tcx().mk_box(content_ty)); let llty_ptr = bx.cx().backend_type(box_layout); diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs index 3757c514d2c..02be098599b 100644 --- a/src/librustc_codegen_ssa/traits/builder.rs +++ b/src/librustc_codegen_ssa/traits/builder.rs @@ -15,10 +15,10 @@ use super::intrinsic::IntrinsicCallMethods; use super::type_::ArgTypeMethods; use super::HasCodegen; use common::{AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope}; -use std::ffi::CStr; use mir::operand::OperandRef; use mir::place::PlaceRef; -use rustc::ty::layout::{Align, Size}; +use rustc::ty::layout::{AbiAndPrefAlign, Size}; +use std::ffi::CStr; use MemFlags; use std::borrow::Cow; @@ -97,17 +97,18 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: fn fneg(&mut self, v: Self::Value) -> Self::Value; fn not(&mut self, v: Self::Value) -> Self::Value; - fn alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value; - fn dynamic_alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value; + fn alloca(&mut self, ty: Self::Type, name: &str, align: AbiAndPrefAlign) -> Self::Value; + fn dynamic_alloca(&mut self, ty: Self::Type, name: &str, align: AbiAndPrefAlign) + -> Self::Value; fn array_alloca( &mut self, ty: Self::Type, len: Self::Value, name: &str, - align: Align, + align: AbiAndPrefAlign, ) -> Self::Value; - fn load(&mut self, ptr: Self::Value, align: Align) -> Self::Value; + fn load(&mut self, ptr: Self::Value, align: AbiAndPrefAlign) -> Self::Value; fn volatile_load(&mut self, ptr: Self::Value) -> Self::Value; fn atomic_load(&mut self, ptr: Self::Value, order: AtomicOrdering, size: Size) -> Self::Value; fn load_operand(&mut self, place: PlaceRef<'tcx, Self::Value>) @@ -116,12 +117,12 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: fn range_metadata(&mut self, load: Self::Value, range: Range); fn nonnull_metadata(&mut self, load: Self::Value); - fn store(&mut self, val: Self::Value, ptr: Self::Value, align: Align) -> Self::Value; + fn store(&mut self, val: Self::Value, ptr: Self::Value, align: AbiAndPrefAlign) -> Self::Value; fn store_with_flags( &mut self, val: Self::Value, ptr: Self::Value, - align: Align, + align: AbiAndPrefAlign, flags: MemFlags, ) -> Self::Value; fn atomic_store( @@ -174,18 +175,18 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: fn memcpy( &mut self, dst: Self::Value, - dst_align: Align, + dst_align: AbiAndPrefAlign, src: Self::Value, - src_align: Align, + src_align: AbiAndPrefAlign, size: Self::Value, flags: MemFlags, ); fn memmove( &mut self, dst: Self::Value, - dst_align: Align, + dst_align: AbiAndPrefAlign, src: Self::Value, - src_align: Align, + src_align: AbiAndPrefAlign, size: Self::Value, flags: MemFlags, ); @@ -194,7 +195,7 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: ptr: Self::Value, fill_byte: Self::Value, size: Self::Value, - align: Align, + align: AbiAndPrefAlign, flags: MemFlags, ); diff --git a/src/librustc_codegen_ssa/traits/statics.rs b/src/librustc_codegen_ssa/traits/statics.rs index 172c48f8a85..b66f4378c35 100644 --- a/src/librustc_codegen_ssa/traits/statics.rs +++ b/src/librustc_codegen_ssa/traits/statics.rs @@ -10,13 +10,23 @@ use super::Backend; use rustc::hir::def_id::DefId; -use rustc::ty::layout::Align; +use rustc::ty::layout::AbiAndPrefAlign; pub trait StaticMethods<'tcx>: Backend<'tcx> { fn static_ptrcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value; fn static_bitcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value; - fn static_addr_of_mut(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value; - fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value; + fn static_addr_of_mut( + &self, + cv: Self::Value, + align: AbiAndPrefAlign, + kind: Option<&str>, + ) -> Self::Value; + fn static_addr_of( + &self, + cv: Self::Value, + align: AbiAndPrefAlign, + kind: Option<&str>, + ) -> Self::Value; fn get_static(&self, def_id: DefId) -> Self::Value; fn codegen_static(&self, def_id: DefId, is_mutable: bool); unsafe fn static_replace_all_uses(&self, old_g: Self::Value, new_g: Self::Value); diff --git a/src/librustc_codegen_ssa/traits/type_.rs b/src/librustc_codegen_ssa/traits/type_.rs index 1aa1f45f517..275f378495d 100644 --- a/src/librustc_codegen_ssa/traits/type_.rs +++ b/src/librustc_codegen_ssa/traits/type_.rs @@ -13,7 +13,7 @@ use super::Backend; use super::HasCodegen; use common::{self, TypeKind}; use mir::place::PlaceRef; -use rustc::ty::layout::{self, Align, Size, TyLayout}; +use rustc::ty::layout::{self, AbiAndPrefAlign, Size, TyLayout}; use rustc::ty::{self, Ty}; use rustc::util::nodemap::FxHashMap; use rustc_target::abi::call::{ArgType, CastTarget, FnType, Reg}; @@ -120,7 +120,7 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { } } - fn type_pointee_for_abi_align(&self, align: Align) -> Self::Type { + fn type_pointee_for_abi_align(&self, align: AbiAndPrefAlign) -> Self::Type { // FIXME(eddyb) We could find a better approximation if ity.align < align. let ity = layout::Integer::approximate_abi_align(self, align); self.type_from_integer(ity) @@ -128,7 +128,7 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { /// Return a LLVM type that has at most the required alignment, /// and exactly the required size, as a best-effort padding array. - fn type_padding_filler(&self, size: Size, align: Align) -> Self::Type { + fn type_padding_filler(&self, size: Size, align: AbiAndPrefAlign) -> Self::Type { let unit = layout::Integer::approximate_abi_align(self, align); let size = size.bytes(); let unit_size = unit.size().bytes(); diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 59083413582..69db638270a 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -16,7 +16,7 @@ use rustc::hir::def_id::DefId; use rustc::hir::def::Def; use rustc::mir; use rustc::ty::layout::{ - self, Size, Align, HasDataLayout, LayoutOf, TyLayout + self, Size, AbiAndPrefAlign, HasDataLayout, LayoutOf, TyLayout }; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -314,9 +314,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc &self, metadata: Option>, layout: TyLayout<'tcx>, - ) -> EvalResult<'tcx, Option<(Size, Align)>> { + ) -> EvalResult<'tcx, Option<(Size, AbiAndPrefAlign)>> { if !layout.is_unsized() { - return Ok(Some(layout.size_and_align())); + return Ok(Some((layout.size, layout.align))); } match layout.ty.sty { ty::Adt(..) | ty::Tuple(..) => { @@ -391,8 +391,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc ty::Slice(_) | ty::Str => { let len = metadata.expect("slice fat ptr must have vtable").to_usize(self)?; - let (elem_size, align) = layout.field(self, 0)?.size_and_align(); - Ok(Some((elem_size * len, align))) + let elem = layout.field(self, 0)?; + Ok(Some((elem.size * len, elem.align))) } ty::Foreign(_) => { @@ -406,7 +406,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc pub fn size_and_align_of_mplace( &self, mplace: MPlaceTy<'tcx, M::PointerTag> - ) -> EvalResult<'tcx, Option<(Size, Align)>> { + ) -> EvalResult<'tcx, Option<(Size, AbiAndPrefAlign)>> { self.size_and_align_of(mplace.meta, mplace.layout) } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 7dd42c66649..dbb0e522874 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -21,7 +21,7 @@ use std::ptr; use std::borrow::Cow; use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt}; -use rustc::ty::layout::{self, Align, TargetDataLayout, Size, HasDataLayout}; +use rustc::ty::layout::{self, AbiAndPrefAlign, TargetDataLayout, Size, HasDataLayout}; pub use rustc::mir::interpret::{truncate, write_target_uint, read_target_uint}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; @@ -71,7 +71,7 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { /// To be able to compare pointers with NULL, and to check alignment for accesses /// to ZSTs (where pointers may dangle), we keep track of the size even for allocations /// that do not exist any more. - dead_alloc_map: FxHashMap, + dead_alloc_map: FxHashMap, /// Lets us implement `HasDataLayout`, which is awfully convenient. pub(super) tcx: TyCtxtAt<'a, 'tcx, 'tcx>, @@ -130,7 +130,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn allocate( &mut self, size: Size, - align: Align, + align: AbiAndPrefAlign, kind: MemoryKind, ) -> EvalResult<'tcx, Pointer> { Ok(Pointer::from(self.allocate_with(Allocation::undef(size, align), kind)?)) @@ -140,9 +140,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &mut self, ptr: Pointer, old_size: Size, - old_align: Align, + old_align: AbiAndPrefAlign, new_size: Size, - new_align: Align, + new_align: AbiAndPrefAlign, kind: MemoryKind, ) -> EvalResult<'tcx, Pointer> { if ptr.offset.bytes() != 0 { @@ -179,7 +179,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn deallocate( &mut self, ptr: Pointer, - size_and_align: Option<(Size, Align)>, + size_and_align: Option<(Size, AbiAndPrefAlign)>, kind: MemoryKind, ) -> EvalResult<'tcx> { trace!("deallocating: {}", ptr.alloc_id); @@ -244,7 +244,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn check_align( &self, ptr: Scalar, - required_align: Align + required_align: AbiAndPrefAlign ) -> EvalResult<'tcx> { // Check non-NULL/Undef, extract offset let (offset, alloc_align) = match ptr { @@ -279,7 +279,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } else { let has = offset % required_align.abi(); err!(AlignmentCheckFailed { - has: Align::from_bytes(has, has).unwrap(), + has: AbiAndPrefAlign::from_bytes(has, has).unwrap(), required: required_align, }) } @@ -443,13 +443,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } } - pub fn get_size_and_align(&self, id: AllocId) -> (Size, Align) { + pub fn get_size_and_align(&self, id: AllocId) -> (Size, AbiAndPrefAlign) { if let Ok(alloc) = self.get(id) { return (Size::from_bytes(alloc.bytes.len() as u64), alloc.align); } // Could also be a fn ptr or extern static match self.tcx.alloc_map.lock().get(id) { - Some(AllocType::Function(..)) => (Size::ZERO, Align::from_bytes(1, 1).unwrap()), + Some(AllocType::Function(..)) => { + (Size::ZERO, AbiAndPrefAlign::from_bytes(1, 1).unwrap()) + } Some(AllocType::Static(did)) => { // The only way `get` couldn't have worked here is if this is an extern static assert!(self.tcx.is_foreign_item(did)); @@ -622,7 +624,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &self, ptr: Pointer, size: Size, - align: Align, + align: AbiAndPrefAlign, check_defined_and_ptr: bool, ) -> EvalResult<'tcx, &[u8]> { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); @@ -651,7 +653,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &self, ptr: Pointer, size: Size, - align: Align + align: AbiAndPrefAlign ) -> EvalResult<'tcx, &[u8]> { self.get_bytes_internal(ptr, size, align, true) } @@ -663,7 +665,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &self, ptr: Pointer, size: Size, - align: Align + align: AbiAndPrefAlign ) -> EvalResult<'tcx, &[u8]> { self.get_bytes_internal(ptr, size, align, false) } @@ -674,7 +676,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &mut self, ptr: Pointer, size: Size, - align: Align, + align: AbiAndPrefAlign, ) -> EvalResult<'tcx, &mut [u8]> { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); self.check_align(ptr.into(), align)?; @@ -747,9 +749,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn copy( &mut self, src: Scalar, - src_align: Align, + src_align: AbiAndPrefAlign, dest: Scalar, - dest_align: Align, + dest_align: AbiAndPrefAlign, size: Size, nonoverlapping: bool, ) -> EvalResult<'tcx> { @@ -759,9 +761,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn copy_repeatedly( &mut self, src: Scalar, - src_align: Align, + src_align: AbiAndPrefAlign, dest: Scalar, - dest_align: Align, + dest_align: AbiAndPrefAlign, size: Size, length: u64, nonoverlapping: bool, @@ -863,7 +865,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { allow_ptr_and_undef: bool, ) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = Align::from_bytes(1, 1).unwrap(); + let align = AbiAndPrefAlign::from_bytes(1, 1).unwrap(); if size.bytes() == 0 { self.check_align(ptr, align)?; return Ok(()); @@ -881,7 +883,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = Align::from_bytes(1, 1).unwrap(); + let align = AbiAndPrefAlign::from_bytes(1, 1).unwrap(); if size.bytes() == 0 { self.check_align(ptr, align)?; return Ok(&[]); @@ -891,7 +893,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = Align::from_bytes(1, 1).unwrap(); + let align = AbiAndPrefAlign::from_bytes(1, 1).unwrap(); if src.is_empty() { self.check_align(ptr, align)?; return Ok(()); @@ -908,7 +910,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { count: Size ) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = Align::from_bytes(1, 1).unwrap(); + let align = AbiAndPrefAlign::from_bytes(1, 1).unwrap(); if count.bytes() == 0 { self.check_align(ptr, align)?; return Ok(()); @@ -924,7 +926,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn read_scalar( &self, ptr: Pointer, - ptr_align: Align, + ptr_align: AbiAndPrefAlign, size: Size ) -> EvalResult<'tcx, ScalarMaybeUndef> { // get_bytes_unchecked tests alignment and relocation edges @@ -961,7 +963,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn read_ptr_sized( &self, ptr: Pointer, - ptr_align: Align + ptr_align: AbiAndPrefAlign ) -> EvalResult<'tcx, ScalarMaybeUndef> { self.read_scalar(ptr, ptr_align, self.pointer_size()) } @@ -970,7 +972,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn write_scalar( &mut self, ptr: Pointer, - ptr_align: Align, + ptr_align: AbiAndPrefAlign, val: ScalarMaybeUndef, type_size: Size, ) -> EvalResult<'tcx> { @@ -1017,14 +1019,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn write_ptr_sized( &mut self, ptr: Pointer, - ptr_align: Align, + ptr_align: AbiAndPrefAlign, val: ScalarMaybeUndef ) -> EvalResult<'tcx> { let ptr_size = self.pointer_size(); self.write_scalar(ptr.into(), ptr_align, val, ptr_size) } - fn int_align(&self, size: Size) -> Align { + fn int_align(&self, size: Size) -> AbiAndPrefAlign { // We assume pointer-sized integers have the same alignment as pointers. // We also assume signed and unsigned integers of the same size have the same alignment. let ity = match size.bytes() { diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 9f248d46350..bd713d4462d 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -18,7 +18,7 @@ use std::hash::Hash; use rustc::hir; use rustc::mir; use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx}; +use rustc::ty::layout::{self, Size, AbiAndPrefAlign, LayoutOf, TyLayout, HasDataLayout, VariantIdx}; use super::{ GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic, @@ -32,7 +32,7 @@ pub struct MemPlace { /// be turned back into a reference before ever being dereferenced. /// However, it may never be undef. pub ptr: Scalar, - pub align: Align, + pub align: AbiAndPrefAlign, /// Metadata for unsized places. Interpretation is up to the type. /// Must not be present for sized types, but can be missing for unsized types /// (e.g. `extern type`). @@ -116,7 +116,7 @@ impl MemPlace { } #[inline(always)] - pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self { + pub fn from_scalar_ptr(ptr: Scalar, align: AbiAndPrefAlign) -> Self { MemPlace { ptr, align, @@ -127,16 +127,16 @@ impl MemPlace { /// Produces a Place that will error if attempted to be read from or written to #[inline(always)] pub fn null(cx: &impl HasDataLayout) -> Self { - Self::from_scalar_ptr(Scalar::ptr_null(cx), Align::from_bytes(1, 1).unwrap()) + Self::from_scalar_ptr(Scalar::ptr_null(cx), AbiAndPrefAlign::from_bytes(1, 1).unwrap()) } #[inline(always)] - pub fn from_ptr(ptr: Pointer, align: Align) -> Self { + pub fn from_ptr(ptr: Pointer, align: AbiAndPrefAlign) -> Self { Self::from_scalar_ptr(ptr.into(), align) } #[inline(always)] - pub fn to_scalar_ptr_align(self) -> (Scalar, Align) { + pub fn to_scalar_ptr_align(self) -> (Scalar, AbiAndPrefAlign) { assert!(self.meta.is_none()); (self.ptr, self.align) } @@ -230,12 +230,12 @@ impl<'tcx, Tag: ::std::fmt::Debug> Place { } #[inline(always)] - pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self { + pub fn from_scalar_ptr(ptr: Scalar, align: AbiAndPrefAlign) -> Self { Place::Ptr(MemPlace::from_scalar_ptr(ptr, align)) } #[inline(always)] - pub fn from_ptr(ptr: Pointer, align: Align) -> Self { + pub fn from_ptr(ptr: Pointer, align: AbiAndPrefAlign) -> Self { Place::Ptr(MemPlace::from_ptr(ptr, align)) } @@ -249,7 +249,7 @@ impl<'tcx, Tag: ::std::fmt::Debug> Place { } #[inline] - pub fn to_scalar_ptr_align(self) -> (Scalar, Align) { + pub fn to_scalar_ptr_align(self) -> (Scalar, AbiAndPrefAlign) { self.to_mem_place().to_scalar_ptr_align() } diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs index 4b63335ad96..56475dffae4 100644 --- a/src/librustc_mir/interpret/snapshot.rs +++ b/src/librustc_mir/interpret/snapshot.rs @@ -16,7 +16,7 @@ use rustc::mir::interpret::{ }; use rustc::ty::{self, TyCtxt}; -use rustc::ty::layout::Align; +use rustc::ty::layout::AbiAndPrefAlign; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -276,7 +276,7 @@ struct AllocationSnapshot<'a> { bytes: &'a [u8], relocations: Relocations<(), AllocIdSnapshot<'a>>, undef_mask: &'a UndefMask, - align: &'a Align, + align: &'a AbiAndPrefAlign, mutability: &'a Mutability, } diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index c5366a5ce6a..f1bedd181e9 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -9,7 +9,7 @@ // except according to those terms. use rustc::ty::{self, Ty}; -use rustc::ty::layout::{Size, Align, LayoutOf}; +use rustc::ty::layout::{Size, AbiAndPrefAlign, LayoutOf}; use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic}; use super::{EvalContext, Machine, MemoryKind}; @@ -101,7 +101,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> pub fn read_size_and_align_from_vtable( &self, vtable: Pointer, - ) -> EvalResult<'tcx, (Size, Align)> { + ) -> EvalResult<'tcx, (Size, AbiAndPrefAlign)> { let pointer_size = self.pointer_size(); let pointer_align = self.tcx.data_layout.pointer_align; let size = self.memory.read_ptr_sized(vtable.offset(pointer_size, self)?,pointer_align)? @@ -110,6 +110,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> vtable.offset(pointer_size * 2, self)?, pointer_align )?.to_bits(pointer_size)? as u64; - Ok((Size::from_bytes(size), Align::from_bytes(align, align).unwrap())) + Ok((Size::from_bytes(size), AbiAndPrefAlign::from_bytes(align, align).unwrap())) } } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index ad7ffd291be..41358fe0d84 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -13,7 +13,7 @@ use std::hash::Hash; use std::ops::RangeInclusive; use syntax_pos::symbol::Symbol; -use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx}; +use rustc::ty::layout::{self, Size, AbiAndPrefAlign, TyLayout, LayoutOf, VariantIdx}; use rustc::ty; use rustc_data_structures::fx::FxHashSet; use rustc::mir::interpret::{ @@ -355,7 +355,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> // for the purpose of validity, consider foreign types to have // alignment and size determined by the layout (size will be 0, // alignment should take attributes into account). - .unwrap_or_else(|| layout.size_and_align()); + .unwrap_or_else(|| (layout.size, layout.align)); match self.ecx.memory.check_align(ptr, align) { Ok(_) => {}, Err(err) => { @@ -463,7 +463,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> // for function pointers. let non_null = self.ecx.memory.check_align( - Scalar::Ptr(ptr), Align::from_bytes(1, 1).unwrap() + Scalar::Ptr(ptr), AbiAndPrefAlign::from_bytes(1, 1).unwrap() ).is_ok() || self.ecx.memory.get_fn(ptr).is_ok(); if !non_null { diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index 8f9ef2544e6..289a76eae8f 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use abi::{self, Abi, Align, FieldPlacement, Size}; +use abi::{self, Abi, AbiAndPrefAlign, FieldPlacement, Size}; use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; use spec::HasTargetSpec; @@ -80,7 +80,7 @@ mod attr_impl { pub struct ArgAttributes { pub regular: ArgAttribute, pub pointee_size: Size, - pub pointee_align: Option + pub pointee_align: Option } impl ArgAttributes { @@ -137,7 +137,7 @@ impl Reg { } impl Reg { - pub fn align(&self, cx: &C) -> Align { + pub fn align(&self, cx: &C) -> AbiAndPrefAlign { let dl = cx.data_layout(); match self.kind { RegKind::Integer => { @@ -188,7 +188,7 @@ impl From for Uniform { } impl Uniform { - pub fn align(&self, cx: &C) -> Align { + pub fn align(&self, cx: &C) -> AbiAndPrefAlign { self.unit.align(cx) } } @@ -230,7 +230,7 @@ impl CastTarget { .abi_align(self.rest.align(cx)) + self.rest.total } - pub fn align(&self, cx: &C) -> Align { + pub fn align(&self, cx: &C) -> AbiAndPrefAlign { self.prefix.iter() .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk }.align(cx))) .fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)), diff --git a/src/librustc_target/abi/call/powerpc64.rs b/src/librustc_target/abi/call/powerpc64.rs index f7ef1390f14..93b8f79ccdc 100644 --- a/src/librustc_target/abi/call/powerpc64.rs +++ b/src/librustc_target/abi/call/powerpc64.rs @@ -13,7 +13,7 @@ // need to be fixed when PowerPC vector support is added. use abi::call::{FnType, ArgType, Reg, RegKind, Uniform}; -use abi::{Align, Endian, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use abi::{AbiAndPrefAlign, Endian, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; use spec::HasTargetSpec; #[derive(Debug, Clone, Copy, PartialEq)] @@ -120,7 +120,7 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>, abi: ABI) } else { // Aggregates larger than a doubleword should be padded // at the tail to fill out a whole number of doublewords. - let align = Align::from_bits(64, 64).unwrap(); + let align = AbiAndPrefAlign::from_bits(64, 64).unwrap(); (Reg::i64(), size.abi_align(align)) }; diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 22afb0da05b..7b0b34e207c 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -24,20 +24,21 @@ pub mod call; /// for a target, which contains everything needed to compute layouts. pub struct TargetDataLayout { pub endian: Endian, - pub i1_align: Align, - pub i8_align: Align, - pub i16_align: Align, - pub i32_align: Align, - pub i64_align: Align, - pub i128_align: Align, - pub f32_align: Align, - pub f64_align: Align, + pub i1_align: AbiAndPrefAlign, + pub i8_align: AbiAndPrefAlign, + pub i16_align: AbiAndPrefAlign, + pub i32_align: AbiAndPrefAlign, + pub i64_align: AbiAndPrefAlign, + pub i128_align: AbiAndPrefAlign, + pub f32_align: AbiAndPrefAlign, + pub f64_align: AbiAndPrefAlign, pub pointer_size: Size, - pub pointer_align: Align, - pub aggregate_align: Align, + pub pointer_align: AbiAndPrefAlign, + pub aggregate_align: AbiAndPrefAlign, /// Alignments for vector types. - pub vector_align: Vec<(Size, Align)>, + pub vector_align: Vec<(Size, AbiAndPrefAlign)>, + pub instruction_address_space: u32, } @@ -46,20 +47,20 @@ impl Default for TargetDataLayout { fn default() -> TargetDataLayout { TargetDataLayout { endian: Endian::Big, - i1_align: Align::from_bits(8, 8).unwrap(), - i8_align: Align::from_bits(8, 8).unwrap(), - i16_align: Align::from_bits(16, 16).unwrap(), - i32_align: Align::from_bits(32, 32).unwrap(), - i64_align: Align::from_bits(32, 64).unwrap(), - i128_align: Align::from_bits(32, 64).unwrap(), - f32_align: Align::from_bits(32, 32).unwrap(), - f64_align: Align::from_bits(64, 64).unwrap(), + i1_align: AbiAndPrefAlign::from_bits(8, 8).unwrap(), + i8_align: AbiAndPrefAlign::from_bits(8, 8).unwrap(), + i16_align: AbiAndPrefAlign::from_bits(16, 16).unwrap(), + i32_align: AbiAndPrefAlign::from_bits(32, 32).unwrap(), + i64_align: AbiAndPrefAlign::from_bits(32, 64).unwrap(), + i128_align: AbiAndPrefAlign::from_bits(32, 64).unwrap(), + f32_align: AbiAndPrefAlign::from_bits(32, 32).unwrap(), + f64_align: AbiAndPrefAlign::from_bits(64, 64).unwrap(), pointer_size: Size::from_bits(64), - pointer_align: Align::from_bits(64, 64).unwrap(), - aggregate_align: Align::from_bits(0, 64).unwrap(), + pointer_align: AbiAndPrefAlign::from_bits(64, 64).unwrap(), + aggregate_align: AbiAndPrefAlign::from_bits(0, 64).unwrap(), vector_align: vec![ - (Size::from_bits(64), Align::from_bits(64, 64).unwrap()), - (Size::from_bits(128), Align::from_bits(128, 128).unwrap()) + (Size::from_bits(64), AbiAndPrefAlign::from_bits(64, 64).unwrap()), + (Size::from_bits(128), AbiAndPrefAlign::from_bits(128, 128).unwrap()) ], instruction_address_space: 0, } @@ -96,7 +97,7 @@ impl TargetDataLayout { } let abi = parse_bits(s[0], "alignment", cause)?; let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?; - Align::from_bits(abi, pref).map_err(|err| { + AbiAndPrefAlign::from_bits(abi, pref).map_err(|err| { format!("invalid alignment for `{}` in \"data-layout\": {}", cause, err) }) @@ -205,7 +206,7 @@ impl TargetDataLayout { } } - pub fn vector_align(&self, vec_size: Size) -> Align { + pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign { for &(size, align) in &self.vector_align { if size == vec_size { return align; @@ -214,7 +215,7 @@ impl TargetDataLayout { // Default to natural alignment, which is what LLVM does. // That is, use the size, rounded up to a power of 2. let align = vec_size.bytes().next_power_of_two(); - Align::from_bytes(align, align).unwrap() + AbiAndPrefAlign::from_bytes(align, align).unwrap() } } @@ -270,13 +271,13 @@ impl Size { } #[inline] - pub fn abi_align(self, align: Align) -> Size { + pub fn abi_align(self, align: AbiAndPrefAlign) -> Size { let mask = align.abi() - 1; Size::from_bytes((self.bytes() + mask) & !mask) } #[inline] - pub fn is_abi_aligned(self, align: Align) -> bool { + pub fn is_abi_aligned(self, align: AbiAndPrefAlign) -> bool { let mask = align.abi() - 1; self.bytes() & mask == 0 } @@ -358,23 +359,23 @@ impl AddAssign for Size { } } -/// Alignment of a type in bytes, both ABI-mandated and preferred. +/// Alignments of a type in bytes, both ABI-mandated and preferred. /// Each field is a power of two, giving the alignment a maximum value /// of 2(28 - 1), which is limited by LLVM to a /// maximum capacity of 229 or 536870912. #[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)] -pub struct Align { +pub struct AbiAndPrefAlign { abi_pow2: u8, pref_pow2: u8, } -impl Align { - pub fn from_bits(abi: u64, pref: u64) -> Result { - Align::from_bytes(Size::from_bits(abi).bytes(), +impl AbiAndPrefAlign { + pub fn from_bits(abi: u64, pref: u64) -> Result { + AbiAndPrefAlign::from_bytes(Size::from_bits(abi).bytes(), Size::from_bits(pref).bytes()) } - pub fn from_bytes(abi: u64, pref: u64) -> Result { + pub fn from_bytes(abi: u64, pref: u64) -> Result { let log2 = |align: u64| { // Treat an alignment of 0 bytes like 1-byte alignment. if align == 0 { @@ -396,7 +397,7 @@ impl Align { } }; - Ok(Align { + Ok(AbiAndPrefAlign { abi_pow2: log2(abi)?, pref_pow2: log2(pref)?, }) @@ -418,15 +419,15 @@ impl Align { self.pref() * 8 } - pub fn min(self, other: Align) -> Align { - Align { + pub fn min(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign { + AbiAndPrefAlign { abi_pow2: cmp::min(self.abi_pow2, other.abi_pow2), pref_pow2: cmp::min(self.pref_pow2, other.pref_pow2), } } - pub fn max(self, other: Align) -> Align { - Align { + pub fn max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign { + AbiAndPrefAlign { abi_pow2: cmp::max(self.abi_pow2, other.abi_pow2), pref_pow2: cmp::max(self.pref_pow2, other.pref_pow2), } @@ -436,9 +437,9 @@ impl Align { /// (the largest power of two that the offset is a multiple of). /// /// NB: for an offset of `0`, this happens to return `2^64`. - pub fn max_for_offset(offset: Size) -> Align { + pub fn max_for_offset(offset: Size) -> AbiAndPrefAlign { let pow2 = offset.bytes().trailing_zeros() as u8; - Align { + AbiAndPrefAlign { abi_pow2: pow2, pref_pow2: pow2, } @@ -446,8 +447,8 @@ impl Align { /// Lower the alignment, if necessary, such that the given offset /// is aligned to it (the offset is a multiple of the alignment). - pub fn restrict_for_offset(self, offset: Size) -> Align { - self.min(Align::max_for_offset(offset)) + pub fn restrict_for_offset(self, offset: Size) -> AbiAndPrefAlign { + self.min(AbiAndPrefAlign::max_for_offset(offset)) } } @@ -472,7 +473,7 @@ impl Integer { } } - pub fn align(self, cx: &C) -> Align { + pub fn align(self, cx: &C) -> AbiAndPrefAlign { let dl = cx.data_layout(); match self { @@ -507,7 +508,7 @@ impl Integer { } /// Find the smallest integer with the given alignment. - pub fn for_abi_align(cx: &C, align: Align) -> Option { + pub fn for_abi_align(cx: &C, align: AbiAndPrefAlign) -> Option { let dl = cx.data_layout(); let wanted = align.abi(); @@ -520,7 +521,7 @@ impl Integer { } /// Find the largest integer with the given alignment or less. - pub fn approximate_abi_align(cx: &C, align: Align) -> Integer { + pub fn approximate_abi_align(cx: &C, align: AbiAndPrefAlign) -> Integer { let dl = cx.data_layout(); let wanted = align.abi(); @@ -597,7 +598,7 @@ impl<'a, 'tcx> Primitive { } } - pub fn align(self, cx: &C) -> Align { + pub fn align(self, cx: &C) -> AbiAndPrefAlign { let dl = cx.data_layout(); match self { @@ -868,7 +869,7 @@ pub struct LayoutDetails { pub variants: Variants, pub fields: FieldPlacement, pub abi: Abi, - pub align: Align, + pub align: AbiAndPrefAlign, pub size: Size } @@ -949,8 +950,4 @@ impl<'a, Ty> TyLayout<'a, Ty> { Abi::Aggregate { sized } => sized && self.size.bytes() == 0 } } - - pub fn size_and_align(&self) -> (Size, Align) { - (self.size, self.align) - } } From 3ce8d444affefb61ee733aa21da7f1ebc1b515e9 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 9 Sep 2018 00:22:22 +0300 Subject: [PATCH 0142/1984] rustc_target: separate out an individual Align from AbiAndPrefAlign. --- src/librustc/mir/interpret/allocation.rs | 4 +- src/librustc/mir/interpret/error.rs | 7 +- src/librustc/session/code_stats.rs | 2 +- src/librustc/ty/layout.rs | 32 ++-- src/librustc_codegen_llvm/abi.rs | 4 +- src/librustc_codegen_llvm/builder.rs | 18 +- src/librustc_codegen_llvm/consts.rs | 10 +- .../debuginfo/metadata.rs | 28 +-- src/librustc_codegen_llvm/debuginfo/mod.rs | 2 +- src/librustc_codegen_llvm/intrinsic.rs | 12 +- src/librustc_codegen_llvm/type_of.rs | 10 +- src/librustc_codegen_ssa/glue.rs | 6 +- src/librustc_codegen_ssa/meth.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 6 +- src/librustc_codegen_ssa/mir/operand.rs | 6 +- src/librustc_codegen_ssa/mir/place.rs | 8 +- src/librustc_codegen_ssa/mir/rvalue.rs | 2 +- src/librustc_mir/const_eval.rs | 2 +- src/librustc_mir/interpret/eval_context.rs | 4 +- src/librustc_mir/interpret/intrinsics.rs | 2 +- src/librustc_mir/interpret/memory.rs | 22 +-- src/librustc_mir/interpret/place.rs | 15 +- src/librustc_mir/interpret/traits.rs | 6 +- src/librustc_mir/interpret/validity.rs | 4 +- src/librustc_mir/util/alignment.rs | 2 +- src/librustc_target/abi/call/arm.rs | 2 +- src/librustc_target/abi/call/powerpc64.rs | 6 +- src/librustc_target/abi/mod.rs | 178 +++++++++--------- src/librustc_typeck/check/mod.rs | 2 +- 29 files changed, 207 insertions(+), 197 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index eb44c3c8c5f..4e83cc16ab3 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -12,7 +12,7 @@ use super::{Pointer, EvalResult, AllocId}; -use ty::layout::{Size, AbiAndPrefAlign}; +use ty::layout::{Size, Align, AbiAndPrefAlign}; use syntax::ast::Mutability; use std::iter; use mir; @@ -104,7 +104,7 @@ impl Allocation { } pub fn from_byte_aligned_bytes(slice: &[u8]) -> Self { - Allocation::from_bytes(slice, AbiAndPrefAlign::from_bytes(1, 1).unwrap()) + Allocation::from_bytes(slice, AbiAndPrefAlign::new(Align::from_bytes(1).unwrap())) } pub fn undef(size: Size, align: AbiAndPrefAlign) -> Self { diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index bae53a9216a..1a33d362396 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -527,7 +527,7 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> { write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c), AlignmentCheckFailed { required, has } => write!(f, "tried to access memory with alignment {}, but alignment {} is required", - has.abi(), required.abi()), + has.abi.bytes(), required.abi.bytes()), TypeNotPrimitive(ty) => write!(f, "expected primitive type, got {}", ty), Layout(ref err) => @@ -537,8 +537,9 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> { MachineError(ref inner) => write!(f, "{}", inner), IncorrectAllocationInformation(size, size2, align, align2) => - write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and \ - align {}", size.bytes(), align.abi(), size2.bytes(), align2.abi()), + write!(f, "incorrect alloc info: expected size {} and align {}, \ + got size {} and align {}", + size.bytes(), align.abi.bytes(), size2.bytes(), align2.abi.bytes()), Panic { ref msg, line, col, ref file } => write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col), InvalidDiscriminant(val) => diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs index 34a89ccf7a2..7a5ac36420f 100644 --- a/src/librustc/session/code_stats.rs +++ b/src/librustc/session/code_stats.rs @@ -71,7 +71,7 @@ impl CodeStats { let info = TypeSizeInfo { kind, type_description: type_desc.to_string(), - align: align.abi(), + align: align.abi.bytes(), overall_size: overall_size.bytes(), packed: packed, opt_discr_size: opt_discr_size.map(|s| s.bytes()), diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 76c3c467feb..637686fd50e 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -259,7 +259,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let pack = { let pack = repr.pack as u64; - AbiAndPrefAlign::from_bytes(pack, pack).unwrap() + AbiAndPrefAlign::new(Align::from_bytes(pack).unwrap()) }; let mut align = if packed { @@ -274,7 +274,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let mut optimize = !repr.inhibit_struct_field_reordering_opt(); if let StructKind::Prefixed(_, align) = kind { - optimize &= align.abi() == 1; + optimize &= align.abi.bytes() == 1; } if optimize { @@ -285,7 +285,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { }; let optimizing = &mut inverse_memory_index[..end]; let field_align = |f: &TyLayout<'_>| { - if packed { f.align.min(pack).abi() } else { f.align.abi() } + if packed { f.align.min(pack).abi } else { f.align.abi } }; match kind { StructKind::AlwaysSized | @@ -352,7 +352,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { if repr.align > 0 { let repr_align = repr.align as u64; - align = align.max(AbiAndPrefAlign::from_bytes(repr_align, repr_align).unwrap()); + align = align.max(AbiAndPrefAlign::new(Align::from_bytes(repr_align).unwrap())); debug!("univariant repr_align: {:?}", repr_align); } @@ -394,7 +394,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { (Some((i, field)), None, None) => { // Field fills the struct and it has a scalar or scalar pair ABI. if offsets[i].bytes() == 0 && - align.abi() == field.align.abi() && + align.abi == field.align.abi && size == field.size { match field.abi { // For plain scalars, or vectors of them, we can't unpack @@ -682,7 +682,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let pack = { let pack = def.repr.pack as u64; - AbiAndPrefAlign::from_bytes(pack, pack).unwrap() + AbiAndPrefAlign::new(Align::from_bytes(pack).unwrap()) }; let mut align = if packed { @@ -694,7 +694,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { if def.repr.align > 0 { let repr_align = def.repr.align as u64; align = align.max( - AbiAndPrefAlign::from_bytes(repr_align, repr_align).unwrap()); + AbiAndPrefAlign::new(Align::from_bytes(repr_align).unwrap())); } let optimize = !def.repr.inhibit_union_abi_opt(); @@ -964,7 +964,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let mut size = Size::ZERO; // We're interested in the smallest alignment, so start large. - let mut start_align = AbiAndPrefAlign::from_bytes(256, 256).unwrap(); + let mut start_align = AbiAndPrefAlign::new(Align::from_bytes(256).unwrap()); assert_eq!(Integer::for_abi_align(dl, start_align), None); // repr(C) on an enum tells us to make a (tag, union) layout, @@ -989,7 +989,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { // Find the first field we can't move later // to make room for a larger discriminant. for field in st.fields.index_by_increasing_offset().map(|j| field_layouts[j]) { - if !field.is_zst() || field.align.abi() != 1 { + if !field.is_zst() || field.align.abi.bytes() != 1 { start_align = start_align.min(field.align); break; } @@ -1251,7 +1251,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { name: name.to_string(), offset: offset.bytes(), size: field_layout.size.bytes(), - align: field_layout.align.abi(), + align: field_layout.align.abi.bytes(), } } } @@ -1264,7 +1264,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } else { session::SizeKind::Exact }, - align: layout.align.abi(), + align: layout.align.abi.bytes(), size: if min_size.bytes() == 0 { layout.size.bytes() } else { @@ -1994,12 +1994,16 @@ impl_stable_hash_for!(enum ::ty::layout::Primitive { Pointer }); -impl<'gcx> HashStable> for AbiAndPrefAlign { +impl_stable_hash_for!(struct ::ty::layout::AbiAndPrefAlign { + abi, + pref +}); + +impl<'gcx> HashStable> for Align { fn hash_stable(&self, hcx: &mut StableHashingContext<'gcx>, hasher: &mut StableHasher) { - self.abi().hash_stable(hcx, hasher); - self.pref().hash_stable(hcx, hasher); + self.bytes().hash_stable(hcx, hasher); } } diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 76fc5a6eeec..ccab0ce69e3 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -73,7 +73,7 @@ impl ArgAttributesExt for ArgAttributes { if let Some(align) = self.pointee_align { llvm::LLVMRustAddAlignmentAttr(llfn, idx.as_uint(), - align.abi() as u32); + align.abi.bytes() as u32); } regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn)); } @@ -98,7 +98,7 @@ impl ArgAttributesExt for ArgAttributes { if let Some(align) = self.pointee_align { llvm::LLVMRustAddAlignmentCallSiteAttr(callsite, idx.as_uint(), - align.abi() as u32); + align.abi.bytes() as u32); } regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite)); } diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 38400946a91..8da64edc92f 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -475,7 +475,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { llvm::LLVMBuildAlloca(self.llbuilder, ty, name.as_ptr()) }; - llvm::LLVMSetAlignment(alloca, align.abi() as c_uint); + llvm::LLVMSetAlignment(alloca, align.abi.bytes() as c_uint); alloca } } @@ -494,7 +494,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, name.as_ptr()) }; - llvm::LLVMSetAlignment(alloca, align.abi() as c_uint); + llvm::LLVMSetAlignment(alloca, align.abi.bytes() as c_uint); alloca } } @@ -503,7 +503,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { self.count_insn("load"); unsafe { let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); - llvm::LLVMSetAlignment(load, align.abi() as c_uint); + llvm::LLVMSetAlignment(load, align.abi.bytes() as c_uint); load } } @@ -658,7 +658,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let align = if flags.contains(MemFlags::UNALIGNED) { 1 } else { - align.abi() as c_uint + align.abi.bytes() as c_uint }; llvm::LLVMSetAlignment(store, align); if flags.contains(MemFlags::VOLATILE) { @@ -893,8 +893,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let dst = self.pointercast(dst, self.cx().type_i8p()); let src = self.pointercast(src, self.cx().type_i8p()); unsafe { - llvm::LLVMRustBuildMemCpy(self.llbuilder, dst, dst_align.abi() as c_uint, - src, src_align.abi() as c_uint, size, is_volatile); + llvm::LLVMRustBuildMemCpy(self.llbuilder, dst, dst_align.abi.bytes() as c_uint, + src, src_align.abi.bytes() as c_uint, size, is_volatile); } } @@ -913,8 +913,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let dst = self.pointercast(dst, self.cx().type_i8p()); let src = self.pointercast(src, self.cx().type_i8p()); unsafe { - llvm::LLVMRustBuildMemMove(self.llbuilder, dst, dst_align.abi() as c_uint, - src, src_align.abi() as c_uint, size, is_volatile); + llvm::LLVMRustBuildMemMove(self.llbuilder, dst, dst_align.abi.bytes() as c_uint, + src, src_align.abi.bytes() as c_uint, size, is_volatile); } } @@ -930,7 +930,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width); let llintrinsicfn = self.cx().get_intrinsic(&intrinsic_key); let ptr = self.pointercast(ptr, self.cx().type_i8p()); - let align = self.cx().const_u32(align.abi() as u32); + let align = self.cx().const_u32(align.abi.bytes() as u32); let volatile = self.cx().const_bool(flags.contains(MemFlags::VOLATILE)); self.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None); } diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 158bc6eb9c1..b5b2e22fed0 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -28,7 +28,7 @@ use value::Value; use rustc::ty::{self, Ty}; use rustc_codegen_ssa::traits::*; -use rustc::ty::layout::{self, Size, AbiAndPrefAlign, LayoutOf}; +use rustc::ty::layout::{self, Size, Align, AbiAndPrefAlign, LayoutOf}; use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags}; @@ -94,15 +94,15 @@ fn set_global_alignment(cx: &CodegenCx<'ll, '_>, // Note: GCC and Clang also allow `__attribute__((aligned))` on variables, // which can force it to be smaller. Rust doesn't support this yet. if let Some(min) = cx.sess().target.target.options.min_global_align { - match ty::layout::AbiAndPrefAlign::from_bits(min, min) { - Ok(min) => align = align.max(min), + match Align::from_bits(min) { + Ok(min) => align = align.max(AbiAndPrefAlign::new(min)), Err(err) => { cx.sess().err(&format!("invalid minimum global alignment: {}", err)); } } } unsafe { - llvm::LLVMSetAlignment(gv, align.abi() as u32); + llvm::LLVMSetAlignment(gv, align.abi.bytes() as u32); } } @@ -219,7 +219,7 @@ impl StaticMethods<'tcx> for CodegenCx<'ll, 'tcx> { unsafe { // Upgrade the alignment in cases where the same constant is used with different // alignment requirements - let llalign = align.abi() as u32; + let llalign = align.abi.bytes() as u32; if llalign > llvm::LLVMGetAlignment(gv) { llvm::LLVMSetAlignment(gv, llalign); } diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 42b48b728fd..4cee3957042 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -323,7 +323,7 @@ fn fixed_vec_metadata( llvm::LLVMRustDIBuilderCreateArrayType( DIB(cx), size.bits(), - align.abi_bits() as u32, + align.abi.bits() as u32, element_type_metadata, subscripts) }; @@ -787,7 +787,7 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { DIB(cx), name.as_ptr(), size.bits(), - align.abi_bits() as u32, + align.abi.bits() as u32, encoding) }; @@ -818,7 +818,7 @@ fn pointer_type_metadata( DIB(cx), pointee_type_metadata, pointer_size.bits(), - pointer_align.abi_bits() as u32, + pointer_align.abi.bits() as u32, name.as_ptr()) } } @@ -1563,7 +1563,7 @@ fn prepare_enum_metadata( file_metadata, UNKNOWN_LINE_NUMBER, discriminant_size.bits(), - discriminant_align.abi_bits() as u32, + discriminant_align.abi.bits() as u32, create_DIArray(DIB(cx), &enumerators_metadata), discriminant_base_type_metadata, true) }; @@ -1607,7 +1607,7 @@ fn prepare_enum_metadata( file_metadata, UNKNOWN_LINE_NUMBER, layout.size.bits(), - layout.align.abi_bits() as u32, + layout.align.abi.bits() as u32, DIFlags::FlagZero, None, 0, // RuntimeLang @@ -1655,7 +1655,7 @@ fn prepare_enum_metadata( file_metadata, UNKNOWN_LINE_NUMBER, size.bits(), - align.abi_bits() as u32, + align.abi.bits() as u32, layout.fields.offset(0).bits(), DIFlags::FlagArtificial, discr_metadata)) @@ -1675,7 +1675,7 @@ fn prepare_enum_metadata( file_metadata, UNKNOWN_LINE_NUMBER, size.bits(), - align.abi_bits() as u32, + align.abi.bits() as u32, layout.fields.offset(0).bits(), DIFlags::FlagArtificial, discr_metadata)) @@ -1692,7 +1692,7 @@ fn prepare_enum_metadata( file_metadata, UNKNOWN_LINE_NUMBER, layout.size.bits(), - layout.align.abi_bits() as u32, + layout.align.abi.bits() as u32, DIFlags::FlagZero, discriminator_metadata, empty_array, @@ -1709,7 +1709,7 @@ fn prepare_enum_metadata( file_metadata, UNKNOWN_LINE_NUMBER, layout.size.bits(), - layout.align.abi_bits() as u32, + layout.align.abi.bits() as u32, DIFlags::FlagZero, None, type_array, @@ -1803,7 +1803,7 @@ fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>, unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, member_description.size.bits(), - member_description.align.abi_bits() as u32, + member_description.align.abi.bits() as u32, member_description.offset.bits(), match member_description.discriminant { None => None, @@ -1851,7 +1851,7 @@ fn create_struct_stub( unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, struct_size.bits(), - struct_align.abi_bits() as u32, + struct_align.abi.bits() as u32, DIFlags::FlagZero, None, empty_array, @@ -1889,7 +1889,7 @@ fn create_union_stub( unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, union_size.bits(), - union_align.abi_bits() as u32, + union_align.abi.bits() as u32, DIFlags::FlagZero, Some(empty_array), 0, // RuntimeLang @@ -1958,7 +1958,7 @@ pub fn create_global_var_metadata( is_local_to_unit, global, None, - global_align.abi() as u32, + global_align.abi.bytes() as u32, ); } } @@ -1996,7 +1996,7 @@ pub fn create_vtable_metadata( unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, Size::ZERO.bits(), - cx.tcx.data_layout.pointer_align.abi_bits() as u32, + cx.tcx.data_layout.pointer_align.abi.bits() as u32, DIFlags::FlagArtificial, None, empty_array, diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 9784cc6cf9c..199402982c6 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -201,7 +201,7 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { cx.sess().opts.optimize != config::OptLevel::No, DIFlags::FlagZero, argument_index, - align.abi() as u32, + align.abi.bytes() as u32, ) }; source_loc::set_debug_location(self, diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index b2f1f933da4..1756fd5b0b1 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -158,7 +158,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { } "min_align_of" => { let tp_ty = substs.type_at(0); - self.cx().const_usize(self.cx().align_of(tp_ty).abi()) + self.cx().const_usize(self.cx().align_of(tp_ty).abi.bytes()) } "min_align_of_val" => { let tp_ty = substs.type_at(0); @@ -167,12 +167,12 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { glue::size_and_align_of_dst(self, tp_ty, Some(meta)); llalign } else { - self.cx().const_usize(self.cx().align_of(tp_ty).abi()) + self.cx().const_usize(self.cx().align_of(tp_ty).abi.bytes()) } } "pref_align_of" => { let tp_ty = substs.type_at(0); - self.cx().const_usize(self.cx().align_of(tp_ty).pref()) + self.cx().const_usize(self.cx().align_of(tp_ty).pref.bytes()) } "type_name" => { let tp_ty = substs.type_at(0); @@ -261,7 +261,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let align = if name == "unaligned_volatile_load" { 1 } else { - self.cx().align_of(tp_ty).abi() as u32 + self.cx().align_of(tp_ty).abi.bytes() as u32 }; unsafe { llvm::LLVMSetAlignment(load, align); @@ -1436,7 +1436,7 @@ fn generic_simd_intrinsic( // Alignment of T, must be a constant integer value: let alignment_ty = bx.cx().type_i32(); - let alignment = bx.cx().const_i32(bx.cx().align_of(in_elem).abi() as i32); + let alignment = bx.cx().const_i32(bx.cx().align_of(in_elem).abi.bytes() as i32); // Truncate the mask vector to a vector of i1s: let (mask, mask_ty) = { @@ -1536,7 +1536,7 @@ fn generic_simd_intrinsic( // Alignment of T, must be a constant integer value: let alignment_ty = bx.cx().type_i32(); - let alignment = bx.cx().const_i32(bx.cx().align_of(in_elem).abi() as i32); + let alignment = bx.cx().const_i32(bx.cx().align_of(in_elem).abi.bytes() as i32); // Truncate the mask vector to a vector of i1s: let (mask, mask_ty) = { diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index a07fa944891..8ce3be36d0b 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -125,14 +125,14 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, for i in layout.fields.index_by_increasing_offset() { let target_offset = layout.fields.offset(i as usize); let field = layout.field(cx, i); - let effective_field_align = layout.align - .min(field.align) - .restrict_for_offset(target_offset); - packed |= effective_field_align.abi() < field.align.abi(); + let effective_field_align = AbiAndPrefAlign::new(layout.align.abi + .min(field.align.abi) + .restrict_for_offset(target_offset)); + packed |= effective_field_align.abi < field.align.abi; debug!("struct_llfields: {}: {:?} offset: {:?} target_offset: {:?} \ effective_field_align: {}", - i, field, offset, target_offset, effective_field_align.abi()); + i, field, offset, target_offset, effective_field_align.abi.bytes()); assert!(target_offset >= offset); let padding = target_offset - offset; let padding_align = prev_effective_align.min(effective_field_align); diff --git a/src/librustc_codegen_ssa/glue.rs b/src/librustc_codegen_ssa/glue.rs index bf4c53f228e..bb28ea74dc0 100644 --- a/src/librustc_codegen_ssa/glue.rs +++ b/src/librustc_codegen_ssa/glue.rs @@ -30,7 +30,7 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( t, info, layout); if !layout.is_unsized() { let size = bx.cx().const_usize(layout.size.bytes()); - let align = bx.cx().const_usize(layout.align.abi()); + let align = bx.cx().const_usize(layout.align.abi.bytes()); return (size, align); } match t.sty { @@ -44,7 +44,7 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( // The info in this case is the length of the str, so the size is that // times the unit size. (bx.mul(info.unwrap(), bx.cx().const_usize(unit.size.bytes())), - bx.cx().const_usize(unit.align.abi())) + bx.cx().const_usize(unit.align.abi.bytes())) } _ => { // First get the size of all statically known fields. @@ -55,7 +55,7 @@ pub fn size_and_align_of_dst<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( let i = layout.fields.count() - 1; let sized_size = layout.fields.offset(i).bytes(); - let sized_align = layout.align.abi(); + let sized_align = layout.align.abi.bytes(); debug!("DST {} statically sized prefix size: {} align: {}", t, sized_size, sized_align); let sized_size = bx.cx().const_usize(sized_size); diff --git a/src/librustc_codegen_ssa/meth.rs b/src/librustc_codegen_ssa/meth.rs index d0b8c166b12..60268533c85 100644 --- a/src/librustc_codegen_ssa/meth.rs +++ b/src/librustc_codegen_ssa/meth.rs @@ -108,7 +108,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( let components: Vec<_> = [ cx.get_fn(monomorphize::resolve_drop_in_place(cx.tcx(), ty)), cx.const_usize(layout.size.bytes()), - cx.const_usize(layout.align.abi()) + cx.const_usize(layout.align.abi.bytes()) ].iter().cloned().chain(methods).collect(); let vtable_const = cx.const_struct(&components, false); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 1702ad19b76..693addd441f 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -280,7 +280,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { scratch.llval } Ref(llval, _, align) => { - assert_eq!(align.abi(), op.layout.align.abi(), + assert_eq!(align.abi, op.layout.align.abi, "return place is unaligned!"); llval } @@ -805,7 +805,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } Ref(llval, _, align) => { - if arg.is_indirect() && align.abi() < arg.layout.align.abi() { + if arg.is_indirect() && align.abi < arg.layout.align.abi { // `foo(packed.large_field)`. We can't pass the (unaligned) field directly. I // think that ATM (Rust 1.16) we only pass temporaries, but we shouldn't // have scary latent bugs around. @@ -1006,7 +1006,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_place(bx, dest) }; if fn_ret.is_indirect() { - if dest.align.abi() < dest.layout.align.abi() { + if dest.align.abi < dest.layout.align.abi { // Currently, MIR code generation does not create calls // that store directly to fields of packed structs (in // fact, the calls it creates write only to temps), diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 4c92ab7eda5..c604386456c 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -11,7 +11,7 @@ use rustc::mir::interpret::{ConstValue, ErrorHandled}; use rustc::mir; use rustc::ty; -use rustc::ty::layout::{self, AbiAndPrefAlign, LayoutOf, TyLayout}; +use rustc::ty::layout::{self, Align, AbiAndPrefAlign, LayoutOf, TyLayout}; use base; use MemFlags; @@ -348,8 +348,8 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandValue { }; // FIXME: choose an appropriate alignment, or use dynamic align somehow - let max_align = AbiAndPrefAlign::from_bits(128, 128).unwrap(); - let min_align = AbiAndPrefAlign::from_bits(8, 8).unwrap(); + let max_align = AbiAndPrefAlign::new(Align::from_bits(128).unwrap()); + let min_align = AbiAndPrefAlign::new(Align::from_bits(8).unwrap()); // Allocate an appropriate region on the stack, and copy the value into it let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra)); diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index e6216c8724f..f78f7a50561 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -101,7 +101,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { ) -> Self { let field = self.layout.field(bx.cx(), ix); let offset = self.layout.fields.offset(ix); - let effective_field_align = self.align.restrict_for_offset(offset); + let effective_field_align = self.align.abi.restrict_for_offset(offset); let mut simple = || { // Unions and newtypes only use an offset of 0. @@ -123,7 +123,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { None }, layout: field, - align: effective_field_align, + align: AbiAndPrefAlign::new(effective_field_align), } }; @@ -143,7 +143,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { if def.repr.packed() { // FIXME(eddyb) generalize the adjustment when we // start supporting packing to larger alignments. - assert_eq!(self.layout.align.abi(), 1); + assert_eq!(self.layout.align.abi.bytes(), 1); return simple(); } } @@ -197,7 +197,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { llval: bx.pointercast(byte_ptr, bx.cx().type_ptr_to(ll_fty)), llextra: self.llextra, layout: field, - align: effective_field_align, + align: AbiAndPrefAlign::new(effective_field_align), } } diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 167a143ec31..805c1a343d0 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -499,7 +499,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let content_ty = self.monomorphize(&content_ty); let content_layout = bx.cx().layout_of(content_ty); let llsize = bx.cx().const_usize(content_layout.size.bytes()); - let llalign = bx.cx().const_usize(content_layout.align.abi()); + let llalign = bx.cx().const_usize(content_layout.align.abi.bytes()); let box_layout = bx.cx().layout_of(bx.tcx().mk_box(content_ty)); let llty_ptr = bx.cx().backend_type(box_layout); diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 3b32fe21adf..6a8a9fe817c 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -129,7 +129,7 @@ pub fn op_to_const<'tcx>( assert!(meta.is_none()); let ptr = ptr.to_ptr()?; let alloc = ecx.memory.get(ptr.alloc_id)?; - assert!(alloc.align.abi() >= align.abi()); + assert!(alloc.align.abi >= align.abi); assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= op.layout.size.bytes()); let mut alloc = alloc.clone(); alloc.align = align; diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 69db638270a..b3e9008a6b7 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -636,7 +636,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc let (ptr, align) = mplace.to_scalar_ptr_align(); match ptr { Scalar::Ptr(ptr) => { - write!(msg, " by align({}) ref:", align.abi()).unwrap(); + write!(msg, " by align({}) ref:", align.abi.bytes()).unwrap(); allocs.push(ptr.alloc_id); } ptr => write!(msg, " by integral ref: {:?}", ptr).unwrap(), @@ -665,7 +665,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc Place::Ptr(mplace) => { match mplace.ptr { Scalar::Ptr(ptr) => { - trace!("by align({}) ref:", mplace.align.abi()); + trace!("by align({}) ref:", mplace.align.abi.bytes()); self.memory.dump_alloc(ptr.alloc_id); } ptr => trace!(" integral by ref: {:?}", ptr), diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 7ef94005970..bbee6e0b49a 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -60,7 +60,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> match intrinsic_name { "min_align_of" => { let elem_ty = substs.type_at(0); - let elem_align = self.layout_of(elem_ty)?.align.abi(); + let elem_align = self.layout_of(elem_ty)?.align.abi.bytes(); let align_val = Scalar::from_uint(elem_align, dest.layout.size); self.write_scalar(align_val, dest)?; } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index dbb0e522874..681e7329754 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -21,7 +21,7 @@ use std::ptr; use std::borrow::Cow; use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt}; -use rustc::ty::layout::{self, AbiAndPrefAlign, TargetDataLayout, Size, HasDataLayout}; +use rustc::ty::layout::{self, Align, AbiAndPrefAlign, TargetDataLayout, Size, HasDataLayout}; pub use rustc::mir::interpret::{truncate, write_target_uint, read_target_uint}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; @@ -268,18 +268,18 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } }; // Check alignment - if alloc_align.abi() < required_align.abi() { + if alloc_align.abi < required_align.abi { return err!(AlignmentCheckFailed { has: alloc_align, required: required_align, }); } - if offset % required_align.abi() == 0 { + if offset % required_align.abi.bytes() == 0 { Ok(()) } else { - let has = offset % required_align.abi(); + let has = offset % required_align.abi.bytes(); err!(AlignmentCheckFailed { - has: AbiAndPrefAlign::from_bytes(has, has).unwrap(), + has: AbiAndPrefAlign::new(Align::from_bytes(has).unwrap()), required: required_align, }) } @@ -450,7 +450,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // Could also be a fn ptr or extern static match self.tcx.alloc_map.lock().get(id) { Some(AllocType::Function(..)) => { - (Size::ZERO, AbiAndPrefAlign::from_bytes(1, 1).unwrap()) + (Size::ZERO, AbiAndPrefAlign::new(Align::from_bytes(1).unwrap())) } Some(AllocType::Static(did)) => { // The only way `get` couldn't have worked here is if this is an extern static @@ -523,7 +523,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { "{}({} bytes, alignment {}){}", msg, alloc.bytes.len(), - alloc.align.abi(), + alloc.align.abi.bytes(), extra ); @@ -865,7 +865,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { allow_ptr_and_undef: bool, ) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = AbiAndPrefAlign::from_bytes(1, 1).unwrap(); + let align = AbiAndPrefAlign::new(Align::from_bytes(1).unwrap()); if size.bytes() == 0 { self.check_align(ptr, align)?; return Ok(()); @@ -883,7 +883,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = AbiAndPrefAlign::from_bytes(1, 1).unwrap(); + let align = AbiAndPrefAlign::new(Align::from_bytes(1).unwrap()); if size.bytes() == 0 { self.check_align(ptr, align)?; return Ok(&[]); @@ -893,7 +893,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = AbiAndPrefAlign::from_bytes(1, 1).unwrap(); + let align = AbiAndPrefAlign::new(Align::from_bytes(1).unwrap()); if src.is_empty() { self.check_align(ptr, align)?; return Ok(()); @@ -910,7 +910,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { count: Size ) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = AbiAndPrefAlign::from_bytes(1, 1).unwrap(); + let align = AbiAndPrefAlign::new(Align::from_bytes(1).unwrap()); if count.bytes() == 0 { self.check_align(ptr, align)?; return Ok(()); diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index bd713d4462d..ed8b7cf1f90 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -18,7 +18,8 @@ use std::hash::Hash; use rustc::hir; use rustc::mir; use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, Size, AbiAndPrefAlign, LayoutOf, TyLayout, HasDataLayout, VariantIdx}; +use rustc::ty::layout::{self, Size, Align, + AbiAndPrefAlign, LayoutOf, TyLayout, HasDataLayout, VariantIdx}; use super::{ GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic, @@ -127,7 +128,8 @@ impl MemPlace { /// Produces a Place that will error if attempted to be read from or written to #[inline(always)] pub fn null(cx: &impl HasDataLayout) -> Self { - Self::from_scalar_ptr(Scalar::ptr_null(cx), AbiAndPrefAlign::from_bytes(1, 1).unwrap()) + Self::from_scalar_ptr(Scalar::ptr_null(cx), + AbiAndPrefAlign::new(Align::from_bytes(1).unwrap())) } #[inline(always)] @@ -167,7 +169,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> { pub fn dangling(layout: TyLayout<'tcx>, cx: &impl HasDataLayout) -> Self { MPlaceTy { mplace: MemPlace::from_scalar_ptr( - Scalar::from_uint(layout.align.abi(), cx.pointer_size()), + Scalar::from_uint(layout.align.abi.bytes(), cx.pointer_size()), layout.align ), layout @@ -368,10 +370,10 @@ where }; let ptr = base.ptr.ptr_offset(offset, self)?; - let align = base.align + let align = AbiAndPrefAlign::new(base.align.abi // We do not look at `base.layout.align` nor `field_layout.align`, unlike // codegen -- mostly to see if we can get away with that - .restrict_for_offset(offset); // must be last thing that happens + .restrict_for_offset(offset)); // must be last thing that happens Ok(MPlaceTy { mplace: MemPlace { ptr, align, meta }, layout: field_layout }) } @@ -998,7 +1000,8 @@ where if cfg!(debug_assertions) { let (size, align) = self.read_size_and_align_from_vtable(vtable)?; assert_eq!(size, layout.size); - assert_eq!(align.abi(), layout.align.abi()); // only ABI alignment is preserved + // only ABI alignment is preserved + assert_eq!(align.abi, layout.align.abi); } let mplace = MPlaceTy { diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index f1bedd181e9..02843b89812 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -9,7 +9,7 @@ // except according to those terms. use rustc::ty::{self, Ty}; -use rustc::ty::layout::{Size, AbiAndPrefAlign, LayoutOf}; +use rustc::ty::layout::{Size, Align, AbiAndPrefAlign, LayoutOf}; use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic}; use super::{EvalContext, Machine, MemoryKind}; @@ -42,7 +42,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let layout = self.layout_of(ty)?; assert!(!layout.is_unsized(), "can't create a vtable for an unsized type"); let size = layout.size.bytes(); - let align = layout.align.abi(); + let align = layout.align.abi.bytes(); let ptr_size = self.pointer_size(); let ptr_align = self.tcx.data_layout.pointer_align; @@ -110,6 +110,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> vtable.offset(pointer_size * 2, self)?, pointer_align )?.to_bits(pointer_size)? as u64; - Ok((Size::from_bytes(size), AbiAndPrefAlign::from_bytes(align, align).unwrap())) + Ok((Size::from_bytes(size), AbiAndPrefAlign::new(Align::from_bytes(align).unwrap()))) } } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 41358fe0d84..352569b3b64 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -13,7 +13,7 @@ use std::hash::Hash; use std::ops::RangeInclusive; use syntax_pos::symbol::Symbol; -use rustc::ty::layout::{self, Size, AbiAndPrefAlign, TyLayout, LayoutOf, VariantIdx}; +use rustc::ty::layout::{self, Size, Align, AbiAndPrefAlign, TyLayout, LayoutOf, VariantIdx}; use rustc::ty; use rustc_data_structures::fx::FxHashSet; use rustc::mir::interpret::{ @@ -463,7 +463,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> // for function pointers. let non_null = self.ecx.memory.check_align( - Scalar::Ptr(ptr), AbiAndPrefAlign::from_bytes(1, 1).unwrap() + Scalar::Ptr(ptr), AbiAndPrefAlign::new(Align::from_bytes(1).unwrap()) ).is_ok() || self.ecx.memory.get_fn(ptr).is_ok(); if !non_null { diff --git a/src/librustc_mir/util/alignment.rs b/src/librustc_mir/util/alignment.rs index 8717bd08ae4..a96c5dd6870 100644 --- a/src/librustc_mir/util/alignment.rs +++ b/src/librustc_mir/util/alignment.rs @@ -30,7 +30,7 @@ pub fn is_disaligned<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let ty = place.ty(local_decls, tcx).to_ty(tcx); match tcx.layout_raw(param_env.and(ty)) { - Ok(layout) if layout.align.abi() == 1 => { + Ok(layout) if layout.align.abi.bytes() == 1 => { // if the alignment is 1, the type can't be further // disaligned. debug!("is_disaligned({:?}) - align = 1", place); diff --git a/src/librustc_target/abi/call/arm.rs b/src/librustc_target/abi/call/arm.rs index b4ffae7385a..bf497c09bdc 100644 --- a/src/librustc_target/abi/call/arm.rs +++ b/src/librustc_target/abi/call/arm.rs @@ -93,7 +93,7 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>, vfp: bool) } } - let align = arg.layout.align.abi(); + let align = arg.layout.align.abi.bytes(); let total = arg.layout.size; arg.cast_to(Uniform { unit: if align <= 4 { Reg::i32() } else { Reg::i64() }, diff --git a/src/librustc_target/abi/call/powerpc64.rs b/src/librustc_target/abi/call/powerpc64.rs index 93b8f79ccdc..7d78d1d75d5 100644 --- a/src/librustc_target/abi/call/powerpc64.rs +++ b/src/librustc_target/abi/call/powerpc64.rs @@ -13,7 +13,7 @@ // need to be fixed when PowerPC vector support is added. use abi::call::{FnType, ArgType, Reg, RegKind, Uniform}; -use abi::{AbiAndPrefAlign, Endian, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use abi::{Endian, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; use spec::HasTargetSpec; #[derive(Debug, Clone, Copy, PartialEq)] @@ -120,8 +120,8 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>, abi: ABI) } else { // Aggregates larger than a doubleword should be padded // at the tail to fill out a whole number of doublewords. - let align = AbiAndPrefAlign::from_bits(64, 64).unwrap(); - (Reg::i64(), size.abi_align(align)) + let reg_i64 = Reg::i64(); + (reg_i64, size.abi_align(reg_i64.align(cx))) }; arg.cast_to(Uniform { diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 7b0b34e207c..2eabe94754d 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -13,7 +13,7 @@ pub use self::Primitive::*; use spec::Target; -use std::{cmp, fmt}; +use std::fmt; use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; @@ -45,22 +45,23 @@ pub struct TargetDataLayout { impl Default for TargetDataLayout { /// Creates an instance of `TargetDataLayout`. fn default() -> TargetDataLayout { + let align = |bits| Align::from_bits(bits).unwrap(); TargetDataLayout { endian: Endian::Big, - i1_align: AbiAndPrefAlign::from_bits(8, 8).unwrap(), - i8_align: AbiAndPrefAlign::from_bits(8, 8).unwrap(), - i16_align: AbiAndPrefAlign::from_bits(16, 16).unwrap(), - i32_align: AbiAndPrefAlign::from_bits(32, 32).unwrap(), - i64_align: AbiAndPrefAlign::from_bits(32, 64).unwrap(), - i128_align: AbiAndPrefAlign::from_bits(32, 64).unwrap(), - f32_align: AbiAndPrefAlign::from_bits(32, 32).unwrap(), - f64_align: AbiAndPrefAlign::from_bits(64, 64).unwrap(), + i1_align: AbiAndPrefAlign::new(align(8)), + i8_align: AbiAndPrefAlign::new(align(8)), + i16_align: AbiAndPrefAlign::new(align(16)), + i32_align: AbiAndPrefAlign::new(align(32)), + i64_align: AbiAndPrefAlign { abi: align(32), pref: align(64) }, + i128_align: AbiAndPrefAlign { abi: align(32), pref: align(64) }, + f32_align: AbiAndPrefAlign::new(align(32)), + f64_align: AbiAndPrefAlign::new(align(64)), pointer_size: Size::from_bits(64), - pointer_align: AbiAndPrefAlign::from_bits(64, 64).unwrap(), - aggregate_align: AbiAndPrefAlign::from_bits(0, 64).unwrap(), + pointer_align: AbiAndPrefAlign::new(align(64)), + aggregate_align: AbiAndPrefAlign { abi: align(0), pref: align(64) }, vector_align: vec![ - (Size::from_bits(64), AbiAndPrefAlign::from_bits(64, 64).unwrap()), - (Size::from_bits(128), AbiAndPrefAlign::from_bits(128, 128).unwrap()) + (Size::from_bits(64), AbiAndPrefAlign::new(align(64))), + (Size::from_bits(128), AbiAndPrefAlign::new(align(128))), ], instruction_address_space: 0, } @@ -95,11 +96,17 @@ impl TargetDataLayout { if s.is_empty() { return Err(format!("missing alignment for `{}` in \"data-layout\"", cause)); } + let align_from_bits = |bits| { + Align::from_bits(bits).map_err(|err| { + format!("invalid alignment for `{}` in \"data-layout\": {}", + cause, err) + }) + }; let abi = parse_bits(s[0], "alignment", cause)?; let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?; - AbiAndPrefAlign::from_bits(abi, pref).map_err(|err| { - format!("invalid alignment for `{}` in \"data-layout\": {}", - cause, err) + Ok(AbiAndPrefAlign { + abi: align_from_bits(abi)?, + pref: align_from_bits(pref)?, }) }; @@ -214,8 +221,7 @@ impl TargetDataLayout { } // Default to natural alignment, which is what LLVM does. // That is, use the size, rounded up to a power of 2. - let align = vec_size.bytes().next_power_of_two(); - AbiAndPrefAlign::from_bytes(align, align).unwrap() + AbiAndPrefAlign::new(Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap()) } } @@ -272,13 +278,13 @@ impl Size { #[inline] pub fn abi_align(self, align: AbiAndPrefAlign) -> Size { - let mask = align.abi() - 1; + let mask = align.abi.bytes() - 1; Size::from_bytes((self.bytes() + mask) & !mask) } #[inline] pub fn is_abi_aligned(self, align: AbiAndPrefAlign) -> bool { - let mask = align.abi() - 1; + let mask = align.abi.bytes() - 1; self.bytes() & mask == 0 } @@ -359,97 +365,93 @@ impl AddAssign for Size { } } -/// Alignments of a type in bytes, both ABI-mandated and preferred. -/// Each field is a power of two, giving the alignment a maximum value -/// of 2(28 - 1), which is limited by LLVM to a -/// maximum capacity of 229 or 536870912. -#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)] -pub struct AbiAndPrefAlign { - abi_pow2: u8, - pref_pow2: u8, +/// Alignment of a type in bytes (always a power of two). +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] +pub struct Align { + pow2: u8, } -impl AbiAndPrefAlign { - pub fn from_bits(abi: u64, pref: u64) -> Result { - AbiAndPrefAlign::from_bytes(Size::from_bits(abi).bytes(), - Size::from_bits(pref).bytes()) +impl Align { + pub fn from_bits(bits: u64) -> Result { + Align::from_bytes(Size::from_bits(bits).bytes()) } - pub fn from_bytes(abi: u64, pref: u64) -> Result { - let log2 = |align: u64| { - // Treat an alignment of 0 bytes like 1-byte alignment. - if align == 0 { - return Ok(0); - } + pub fn from_bytes(align: u64) -> Result { + // Treat an alignment of 0 bytes like 1-byte alignment. + if align == 0 { + return Ok(Align { pow2: 0 }); + } - let mut bytes = align; - let mut pow: u8 = 0; - while (bytes & 1) == 0 { - pow += 1; - bytes >>= 1; - } - if bytes != 1 { - Err(format!("`{}` is not a power of 2", align)) - } else if pow > 29 { - Err(format!("`{}` is too large", align)) - } else { - Ok(pow) - } - }; + let mut bytes = align; + let mut pow2: u8 = 0; + while (bytes & 1) == 0 { + pow2 += 1; + bytes >>= 1; + } + if bytes != 1 { + return Err(format!("`{}` is not a power of 2", align)); + } + if pow2 > 29 { + return Err(format!("`{}` is too large", align)); + } - Ok(AbiAndPrefAlign { - abi_pow2: log2(abi)?, - pref_pow2: log2(pref)?, - }) + Ok(Align { pow2 }) } - pub fn abi(self) -> u64 { - 1 << self.abi_pow2 + pub fn bytes(self) -> u64 { + 1 << self.pow2 } - pub fn pref(self) -> u64 { - 1 << self.pref_pow2 + pub fn bits(self) -> u64 { + self.bytes() * 8 } - pub fn abi_bits(self) -> u64 { - self.abi() * 8 + /// Compute the best alignment possible for the given offset + /// (the largest power of two that the offset is a multiple of). + /// + /// NB: for an offset of `0`, this happens to return `2^64`. + pub fn max_for_offset(offset: Size) -> Align { + Align { + pow2: offset.bytes().trailing_zeros() as u8, + } } - pub fn pref_bits(self) -> u64 { - self.pref() * 8 + /// Lower the alignment, if necessary, such that the given offset + /// is aligned to it (the offset is a multiple of the alignment). + pub fn restrict_for_offset(self, offset: Size) -> Align { + self.min(Align::max_for_offset(offset)) } +} - pub fn min(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign { +/// A pair of aligments, ABI-mandated and preferred. +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(PartialOrd, Ord)] // FIXME(eddyb) remove (error prone/incorrect) +pub struct AbiAndPrefAlign { + pub abi: Align, + pub pref: Align, +} + +impl AbiAndPrefAlign { + pub fn new(align: Align) -> AbiAndPrefAlign { AbiAndPrefAlign { - abi_pow2: cmp::min(self.abi_pow2, other.abi_pow2), - pref_pow2: cmp::min(self.pref_pow2, other.pref_pow2), + abi: align, + pref: align, } } - pub fn max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign { + pub fn min(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign { AbiAndPrefAlign { - abi_pow2: cmp::max(self.abi_pow2, other.abi_pow2), - pref_pow2: cmp::max(self.pref_pow2, other.pref_pow2), + abi: self.abi.min(other.abi), + pref: self.pref.min(other.pref), } } - /// Compute the best alignment possible for the given offset - /// (the largest power of two that the offset is a multiple of). - /// - /// NB: for an offset of `0`, this happens to return `2^64`. - pub fn max_for_offset(offset: Size) -> AbiAndPrefAlign { - let pow2 = offset.bytes().trailing_zeros() as u8; + pub fn max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign { AbiAndPrefAlign { - abi_pow2: pow2, - pref_pow2: pow2, + abi: self.abi.max(other.abi), + pref: self.pref.max(other.pref), } } - - /// Lower the alignment, if necessary, such that the given offset - /// is aligned to it (the offset is a multiple of the alignment). - pub fn restrict_for_offset(self, offset: Size) -> AbiAndPrefAlign { - self.min(AbiAndPrefAlign::max_for_offset(offset)) - } } /// Integers, also used for enum discriminants. @@ -511,9 +513,9 @@ impl Integer { pub fn for_abi_align(cx: &C, align: AbiAndPrefAlign) -> Option { let dl = cx.data_layout(); - let wanted = align.abi(); + let wanted = align.abi; for &candidate in &[I8, I16, I32, I64, I128] { - if wanted == candidate.align(dl).abi() && wanted == candidate.size().bytes() { + if wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() { return Some(candidate); } } @@ -524,10 +526,10 @@ impl Integer { pub fn approximate_abi_align(cx: &C, align: AbiAndPrefAlign) -> Integer { let dl = cx.data_layout(); - let wanted = align.abi(); + let wanted = align.abi; // FIXME(eddyb) maybe include I128 in the future, when it works everywhere. for &candidate in &[I64, I32, I16] { - if wanted >= candidate.align(dl).abi() && wanted >= candidate.size().bytes() { + if wanted >= candidate.align(dl).abi && wanted.bytes() >= candidate.size().bytes() { return candidate; } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index eed5d909063..02b89a84268 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1779,7 +1779,7 @@ fn check_transparent<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: De // We are currently checking the type this field came from, so it must be local let span = tcx.hir.span_if_local(field.did).unwrap(); let zst = layout.map(|layout| layout.is_zst()).unwrap_or(false); - let align1 = layout.map(|layout| layout.align.abi() == 1).unwrap_or(false); + let align1 = layout.map(|layout| layout.align.abi.bytes() == 1).unwrap_or(false); (span, zst, align1) }); From 5b4747ded7c964ea4e871b3ea6b10bf20862462a Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 9 Sep 2018 01:16:45 +0300 Subject: [PATCH 0143/1984] rustc_target: avoid using AbiAndPrefAlign where possible. --- src/librustc/mir/interpret/allocation.rs | 10 +-- src/librustc/mir/interpret/error.rs | 12 +-- src/librustc/session/code_stats.rs | 6 +- src/librustc/ty/layout.rs | 87 +++++++++---------- src/librustc_codegen_llvm/abi.rs | 14 +-- src/librustc_codegen_llvm/builder.rs | 42 ++++----- src/librustc_codegen_llvm/common.rs | 2 +- src/librustc_codegen_llvm/consts.rs | 14 +-- .../debuginfo/metadata.rs | 36 ++++---- src/librustc_codegen_llvm/debuginfo/mod.rs | 2 +- src/librustc_codegen_llvm/intrinsic.rs | 26 +++--- src/librustc_codegen_llvm/type_of.rs | 32 +++---- src/librustc_codegen_ssa/base.rs | 6 +- src/librustc_codegen_ssa/meth.rs | 6 +- src/librustc_codegen_ssa/mir/block.rs | 26 +++--- src/librustc_codegen_ssa/mir/mod.rs | 4 +- src/librustc_codegen_ssa/mir/operand.rs | 14 +-- src/librustc_codegen_ssa/mir/place.rs | 22 ++--- src/librustc_codegen_ssa/traits/builder.rs | 25 +++--- src/librustc_codegen_ssa/traits/statics.rs | 16 +--- src/librustc_codegen_ssa/traits/type_.rs | 10 +-- src/librustc_mir/const_eval.rs | 2 +- src/librustc_mir/interpret/eval_context.rs | 18 ++-- src/librustc_mir/interpret/memory.rs | 68 +++++++-------- src/librustc_mir/interpret/operand.rs | 2 +- src/librustc_mir/interpret/place.rs | 44 +++++----- src/librustc_mir/interpret/snapshot.rs | 4 +- src/librustc_mir/interpret/terminator.rs | 2 +- src/librustc_mir/interpret/traits.rs | 12 +-- src/librustc_mir/interpret/validity.rs | 6 +- src/librustc_target/abi/call/mips.rs | 6 +- src/librustc_target/abi/call/mips64.rs | 4 +- src/librustc_target/abi/call/mod.rs | 34 ++++---- src/librustc_target/abi/call/powerpc.rs | 6 +- src/librustc_target/abi/call/powerpc64.rs | 2 +- src/librustc_target/abi/call/sparc.rs | 6 +- src/librustc_target/abi/call/x86_64.rs | 2 +- src/librustc_target/abi/mod.rs | 15 ++-- 38 files changed, 311 insertions(+), 334 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 4e83cc16ab3..3250ea266a5 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -12,7 +12,7 @@ use super::{Pointer, EvalResult, AllocId}; -use ty::layout::{Size, Align, AbiAndPrefAlign}; +use ty::layout::{Size, Align}; use syntax::ast::Mutability; use std::iter; use mir; @@ -40,7 +40,7 @@ pub struct Allocation { /// Denotes undefined memory. Reading from undefined memory is forbidden in miri pub undef_mask: UndefMask, /// The alignment of the allocation to detect unaligned reads. - pub align: AbiAndPrefAlign, + pub align: Align, /// Whether the allocation is mutable. /// Also used by codegen to determine if a static should be put into mutable memory, /// which happens for `static mut` and `static` with interior mutability. @@ -90,7 +90,7 @@ impl AllocationExtra<()> for () {} impl Allocation { /// Creates a read-only allocation initialized by the given bytes - pub fn from_bytes(slice: &[u8], align: AbiAndPrefAlign) -> Self { + pub fn from_bytes(slice: &[u8], align: Align) -> Self { let mut undef_mask = UndefMask::new(Size::ZERO); undef_mask.grow(Size::from_bytes(slice.len() as u64), true); Self { @@ -104,10 +104,10 @@ impl Allocation { } pub fn from_byte_aligned_bytes(slice: &[u8]) -> Self { - Allocation::from_bytes(slice, AbiAndPrefAlign::new(Align::from_bytes(1).unwrap())) + Allocation::from_bytes(slice, Align::from_bytes(1).unwrap()) } - pub fn undef(size: Size, align: AbiAndPrefAlign) -> Self { + pub fn undef(size: Size, align: Align) -> Self { assert_eq!(size.bytes() as usize as u64, size.bytes()); Allocation { bytes: vec![0; size.bytes() as usize], diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 1a33d362396..7477343891e 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -13,7 +13,7 @@ use std::{fmt, env}; use hir::map::definitions::DefPathData; use mir; use ty::{self, Ty, layout}; -use ty::layout::{Size, AbiAndPrefAlign, LayoutError}; +use ty::layout::{Size, Align, LayoutError}; use rustc_target::spec::abi::Abi; use super::{RawConst, Pointer, InboundsCheck, ScalarMaybeUndef}; @@ -301,8 +301,8 @@ pub enum EvalErrorKind<'tcx, O> { TlsOutOfBounds, AbiViolation(String), AlignmentCheckFailed { - required: AbiAndPrefAlign, - has: AbiAndPrefAlign, + required: Align, + has: Align, }, ValidationFailure(String), CalledClosureAsFunction, @@ -315,7 +315,7 @@ pub enum EvalErrorKind<'tcx, O> { DeallocatedWrongMemoryKind(String, String), ReallocateNonBasePtr, DeallocateNonBasePtr, - IncorrectAllocationInformation(Size, Size, AbiAndPrefAlign, AbiAndPrefAlign), + IncorrectAllocationInformation(Size, Size, Align, Align), Layout(layout::LayoutError<'tcx>), HeapAllocZeroBytes, HeapAllocNonPowerOfTwoAlignment(u64), @@ -527,7 +527,7 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> { write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c), AlignmentCheckFailed { required, has } => write!(f, "tried to access memory with alignment {}, but alignment {} is required", - has.abi.bytes(), required.abi.bytes()), + has.bytes(), required.bytes()), TypeNotPrimitive(ty) => write!(f, "expected primitive type, got {}", ty), Layout(ref err) => @@ -539,7 +539,7 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> { IncorrectAllocationInformation(size, size2, align, align2) => write!(f, "incorrect alloc info: expected size {} and align {}, \ got size {} and align {}", - size.bytes(), align.abi.bytes(), size2.bytes(), align2.abi.bytes()), + size.bytes(), align.bytes(), size2.bytes(), align2.bytes()), Panic { ref msg, line, col, ref file } => write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col), InvalidDiscriminant(val) => diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs index 7a5ac36420f..b8f5ce3cdbc 100644 --- a/src/librustc/session/code_stats.rs +++ b/src/librustc/session/code_stats.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc_target::abi::{AbiAndPrefAlign, Size}; +use rustc_target::abi::{Align, Size}; use rustc_data_structures::fx::{FxHashSet}; use std::cmp::{self, Ordering}; @@ -63,7 +63,7 @@ impl CodeStats { pub fn record_type_size(&mut self, kind: DataTypeKind, type_desc: S, - align: AbiAndPrefAlign, + align: Align, overall_size: Size, packed: bool, opt_discr_size: Option, @@ -71,7 +71,7 @@ impl CodeStats { let info = TypeSizeInfo { kind, type_description: type_desc.to_string(), - align: align.abi.bytes(), + align: align.bytes(), overall_size: overall_size.bytes(), packed: packed, opt_discr_size: opt_discr_size.map(|s| s.bytes()), diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 637686fd50e..da0a9acede2 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -226,9 +226,10 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { tcx.intern_layout(LayoutDetails::scalar(self, scalar_unit(value))) }; let scalar_pair = |a: Scalar, b: Scalar| { - let align = a.value.align(dl).max(b.value.align(dl)).max(dl.aggregate_align); - let b_offset = a.value.size(dl).abi_align(b.value.align(dl)); - let size = (b_offset + b.value.size(dl)).abi_align(align); + let b_align = b.value.align(dl); + let align = a.value.align(dl).max(b_align).max(dl.aggregate_align); + let b_offset = a.value.size(dl).align_to(b_align.abi); + let size = (b_offset + b.value.size(dl)).align_to(align.abi); LayoutDetails { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Arbitrary { @@ -248,7 +249,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { /// A univariant, the last field of which may be coerced to unsized. MaybeUnsized, /// A univariant, but with a prefix of an arbitrary size & alignment (e.g. enum tag). - Prefixed(Size, AbiAndPrefAlign), + Prefixed(Size, Align), } let univariant_uninterned = |fields: &[TyLayout<'_>], repr: &ReprOptions, kind| { @@ -257,10 +258,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { bug!("struct cannot be packed and aligned"); } - let pack = { - let pack = repr.pack as u64; - AbiAndPrefAlign::new(Align::from_bytes(pack).unwrap()) - }; + let pack = Align::from_bytes(repr.pack as u64).unwrap(); let mut align = if packed { dl.i8_align @@ -274,7 +272,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let mut optimize = !repr.inhibit_struct_field_reordering_opt(); if let StructKind::Prefixed(_, align) = kind { - optimize &= align.abi.bytes() == 1; + optimize &= align.bytes() == 1; } if optimize { @@ -285,7 +283,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { }; let optimizing = &mut inverse_memory_index[..end]; let field_align = |f: &TyLayout<'_>| { - if packed { f.align.min(pack).abi } else { f.align.abi } + if packed { f.align.abi.min(pack) } else { f.align.abi } }; match kind { StructKind::AlwaysSized | @@ -312,13 +310,13 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let mut offset = Size::ZERO; if let StructKind::Prefixed(prefix_size, prefix_align) = kind { - if packed { - let prefix_align = prefix_align.min(pack); - align = align.max(prefix_align); + let prefix_align = if packed { + prefix_align.min(pack) } else { - align = align.max(prefix_align); - } - offset = prefix_size.abi_align(prefix_align); + prefix_align + }; + align = align.max(AbiAndPrefAlign::new(prefix_align)); + offset = prefix_size.align_to(prefix_align); } for &i in &inverse_memory_index { @@ -333,15 +331,13 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } // Invariant: offset < dl.obj_size_bound() <= 1<<61 - if packed { - let field_pack = field.align.min(pack); - offset = offset.abi_align(field_pack); - align = align.max(field_pack); - } - else { - offset = offset.abi_align(field.align); - align = align.max(field.align); - } + let field_align = if packed { + field.align.min(AbiAndPrefAlign::new(pack)) + } else { + field.align + }; + offset = offset.align_to(field_align.abi); + align = align.max(field_align); debug!("univariant offset: {:?} field: {:#?}", offset, field); offsets[i as usize] = offset; @@ -377,7 +373,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { memory_index = inverse_memory_index; } - let size = min_size.abi_align(align); + let size = min_size.align_to(align.abi); let mut abi = Abi::Aggregate { sized }; // Unpack newtype ABIs and find scalar pairs. @@ -648,7 +644,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let size = element.size.checked_mul(count, dl) .ok_or(LayoutError::SizeOverflow(ty))?; let align = dl.vector_align(size); - let size = size.abi_align(align); + let size = size.align_to(align.abi); tcx.intern_layout(LayoutDetails { variants: Variants::Single { index: VariantIdx::new(0) }, @@ -680,10 +676,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { bug!("Union cannot be packed and aligned"); } - let pack = { - let pack = def.repr.pack as u64; - AbiAndPrefAlign::new(Align::from_bytes(pack).unwrap()) - }; + let pack = Align::from_bytes(def.repr.pack as u64).unwrap(); let mut align = if packed { dl.i8_align @@ -704,12 +697,12 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { for field in &variants[index] { assert!(!field.is_unsized()); - if packed { - let field_pack = field.align.min(pack); - align = align.max(field_pack); + let field_align = if packed { + field.align.min(AbiAndPrefAlign::new(pack)) } else { - align = align.max(field.align); - } + field.align + }; + align = align.max(field_align); // If all non-ZST fields have the same ABI, forward this ABI if optimize && !field.is_zst() { @@ -749,7 +742,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { fields: FieldPlacement::Union(variants[index].len()), abi, align, - size: size.abi_align(align) + size: size.align_to(align.abi) })); } @@ -964,19 +957,19 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let mut size = Size::ZERO; // We're interested in the smallest alignment, so start large. - let mut start_align = AbiAndPrefAlign::new(Align::from_bytes(256).unwrap()); - assert_eq!(Integer::for_abi_align(dl, start_align), None); + let mut start_align = Align::from_bytes(256).unwrap(); + assert_eq!(Integer::for_align(dl, start_align), None); // repr(C) on an enum tells us to make a (tag, union) layout, // so we need to grow the prefix alignment to be at least // the alignment of the union. (This value is used both for // determining the alignment of the overall enum, and the // determining the alignment of the payload after the tag.) - let mut prefix_align = min_ity.align(dl); + let mut prefix_align = min_ity.align(dl).abi; if def.repr.c() { for fields in &variants { for field in fields { - prefix_align = prefix_align.max(field.align); + prefix_align = prefix_align.max(field.align.abi); } } } @@ -990,7 +983,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { // to make room for a larger discriminant. for field in st.fields.index_by_increasing_offset().map(|j| field_layouts[j]) { if !field.is_zst() || field.align.abi.bytes() != 1 { - start_align = start_align.min(field.align); + start_align = start_align.min(field.align.abi); break; } } @@ -1000,7 +993,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { }).collect::, _>>()?; // Align the maximum variant size to the largest alignment. - size = size.abi_align(align); + size = size.align_to(align.abi); if size.bytes() >= dl.obj_size_bound() { return Err(LayoutError::SizeOverflow(ty)); @@ -1036,7 +1029,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let mut ity = if def.repr.c() || def.repr.int.is_some() { min_ity } else { - Integer::for_abi_align(dl, start_align).unwrap_or(min_ity) + Integer::for_align(dl, start_align).unwrap_or(min_ity) }; // If the alignment is not larger than the chosen discriminant size, @@ -1204,7 +1197,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let type_desc = format!("{:?}", layout.ty); self.tcx.sess.code_stats.borrow_mut().record_type_size(kind, type_desc, - layout.align, + layout.align.abi, layout.size, packed, opt_discr_size, @@ -1823,7 +1816,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { Abi::ScalarPair(ref a, ref b) => { // HACK(nox): We iter on `b` and then `a` because `max_by_key` // returns the last maximum. - let niche = iter::once((b, a.value.size(self).abi_align(b.value.align(self)))) + let niche = iter::once( + (b, a.value.size(self).align_to(b.value.align(self).abi)) + ) .chain(iter::once((a, Size::ZERO))) .filter_map(|(scalar, offset)| scalar_niche(scalar, offset)) .max_by_key(|niche| niche.available); diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index ccab0ce69e3..3470d6fd0e7 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -73,7 +73,7 @@ impl ArgAttributesExt for ArgAttributes { if let Some(align) = self.pointee_align { llvm::LLVMRustAddAlignmentAttr(llfn, idx.as_uint(), - align.abi.bytes() as u32); + align.bytes() as u32); } regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn)); } @@ -98,7 +98,7 @@ impl ArgAttributesExt for ArgAttributes { if let Some(align) = self.pointee_align { llvm::LLVMRustAddAlignmentCallSiteAttr(callsite, idx.as_uint(), - align.abi.bytes() as u32); + align.bytes() as u32); } regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite)); } @@ -204,7 +204,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { return; } if self.is_sized_indirect() { - OperandValue::Ref(val, None, self.layout.align).store(bx, dst) + OperandValue::Ref(val, None, self.layout.align.abi).store(bx, dst) } else if self.is_unsized_indirect() { bug!("unsized ArgType must be handled through store_fn_arg"); } else if let PassMode::Cast(cast) = self.mode { @@ -214,7 +214,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { if can_store_through_cast_ptr { let cast_ptr_llty = bx.cx().type_ptr_to(cast.llvm_type(bx.cx())); let cast_dst = bx.pointercast(dst.llval, cast_ptr_llty); - bx.store(val, cast_dst, self.layout.align); + bx.store(val, cast_dst, self.layout.align.abi); } else { // The actual return type is a struct, but the ABI // adaptation code has cast it into some scalar type. The @@ -242,7 +242,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { // ...and then memcpy it to the intended destination. bx.memcpy( dst.llval, - self.layout.align, + self.layout.align.abi, llscratch, scratch_align, bx.cx().const_usize(self.layout.size.bytes()), @@ -273,7 +273,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { OperandValue::Pair(next(), next()).store(bx, dst); } PassMode::Indirect(_, Some(_)) => { - OperandValue::Ref(next(), Some(next()), self.layout.align).store(bx, dst); + OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst); } PassMode::Direct(_) | PassMode::Indirect(_, None) | PassMode::Cast(_) => { self.store(bx, next(), dst); @@ -545,7 +545,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { adjust_for_rust_scalar(&mut b_attrs, b, arg.layout, - a.value.size(cx).abi_align(b.value.align(cx)), + a.value.size(cx).align_to(b.value.align(cx).abi), false); arg.mode = PassMode::Pair(a_attrs, b_attrs); return arg; diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 8da64edc92f..d2a99eae340 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -19,7 +19,7 @@ use type_of::LayoutLlvmExt; use value::Value; use libc::{c_uint, c_char}; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::{self, AbiAndPrefAlign, Size, TyLayout}; +use rustc::ty::layout::{self, Align, Size, TyLayout}; use rustc::session::config; use rustc_data_structures::small_c_str::SmallCStr; use rustc_codegen_ssa::traits::*; @@ -457,7 +457,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn alloca(&mut self, ty: &'ll Type, name: &str, align: AbiAndPrefAlign) -> &'ll Value { + fn alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { let mut bx = Builder::with_cx(self.cx); bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) @@ -465,7 +465,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { bx.dynamic_alloca(ty, name, align) } - fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: AbiAndPrefAlign) -> &'ll Value { + fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { self.count_insn("alloca"); unsafe { let alloca = if name.is_empty() { @@ -475,7 +475,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { llvm::LLVMBuildAlloca(self.llbuilder, ty, name.as_ptr()) }; - llvm::LLVMSetAlignment(alloca, align.abi.bytes() as c_uint); + llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint); alloca } } @@ -484,7 +484,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ty: &'ll Type, len: &'ll Value, name: &str, - align: AbiAndPrefAlign) -> &'ll Value { + align: Align) -> &'ll Value { self.count_insn("alloca"); unsafe { let alloca = if name.is_empty() { @@ -494,16 +494,16 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, name.as_ptr()) }; - llvm::LLVMSetAlignment(alloca, align.abi.bytes() as c_uint); + llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint); alloca } } - fn load(&mut self, ptr: &'ll Value, align: AbiAndPrefAlign) -> &'ll Value { + fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value { self.count_insn("load"); unsafe { let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); - llvm::LLVMSetAlignment(load, align.abi.bytes() as c_uint); + llvm::LLVMSetAlignment(load, align.bytes() as c_uint); load } } @@ -639,7 +639,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn store(&mut self, val: &'ll Value, ptr: &'ll Value, align: AbiAndPrefAlign) -> &'ll Value { + fn store(&mut self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value { self.store_with_flags(val, ptr, align, MemFlags::empty()) } @@ -647,7 +647,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { &mut self, val: &'ll Value, ptr: &'ll Value, - align: AbiAndPrefAlign, + align: Align, flags: MemFlags, ) -> &'ll Value { debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags); @@ -658,7 +658,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let align = if flags.contains(MemFlags::UNALIGNED) { 1 } else { - align.abi.bytes() as c_uint + align.bytes() as c_uint }; llvm::LLVMSetAlignment(store, align); if flags.contains(MemFlags::VOLATILE) { @@ -878,8 +878,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn memcpy(&mut self, dst: &'ll Value, dst_align: AbiAndPrefAlign, - src: &'ll Value, src_align: AbiAndPrefAlign, + fn memcpy(&mut self, dst: &'ll Value, dst_align: Align, + src: &'ll Value, src_align: Align, size: &'ll Value, flags: MemFlags) { if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memcpy. @@ -893,13 +893,13 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let dst = self.pointercast(dst, self.cx().type_i8p()); let src = self.pointercast(src, self.cx().type_i8p()); unsafe { - llvm::LLVMRustBuildMemCpy(self.llbuilder, dst, dst_align.abi.bytes() as c_uint, - src, src_align.abi.bytes() as c_uint, size, is_volatile); + llvm::LLVMRustBuildMemCpy(self.llbuilder, dst, dst_align.bytes() as c_uint, + src, src_align.bytes() as c_uint, size, is_volatile); } } - fn memmove(&mut self, dst: &'ll Value, dst_align: AbiAndPrefAlign, - src: &'ll Value, src_align: AbiAndPrefAlign, + fn memmove(&mut self, dst: &'ll Value, dst_align: Align, + src: &'ll Value, src_align: Align, size: &'ll Value, flags: MemFlags) { if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memmove. @@ -913,8 +913,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let dst = self.pointercast(dst, self.cx().type_i8p()); let src = self.pointercast(src, self.cx().type_i8p()); unsafe { - llvm::LLVMRustBuildMemMove(self.llbuilder, dst, dst_align.abi.bytes() as c_uint, - src, src_align.abi.bytes() as c_uint, size, is_volatile); + llvm::LLVMRustBuildMemMove(self.llbuilder, dst, dst_align.bytes() as c_uint, + src, src_align.bytes() as c_uint, size, is_volatile); } } @@ -923,14 +923,14 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ptr: &'ll Value, fill_byte: &'ll Value, size: &'ll Value, - align: AbiAndPrefAlign, + align: Align, flags: MemFlags, ) { let ptr_width = &self.cx().sess().target.target.target_pointer_width; let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width); let llintrinsicfn = self.cx().get_intrinsic(&intrinsic_key); let ptr = self.pointercast(ptr, self.cx().type_i8p()); - let align = self.cx().const_u32(align.abi.bytes() as u32); + let align = self.cx().const_u32(align.bytes() as u32); let volatile = self.cx().const_bool(flags.contains(MemFlags::VOLATILE)); self.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None); } diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index 2fc505d42db..cd74a5854a9 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -357,7 +357,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { offset: Size, ) -> PlaceRef<'tcx, &'ll Value> { let init = const_alloc_to_llvm(self, alloc); - let base_addr = self.static_addr_of(init, layout.align, None); + let base_addr = self.static_addr_of(init, layout.align.abi, None); let llval = unsafe { llvm::LLVMConstInBoundsGEP( self.static_bitcast(base_addr, self.type_i8p()), diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index b5b2e22fed0..07dde2d0301 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -28,7 +28,7 @@ use value::Value; use rustc::ty::{self, Ty}; use rustc_codegen_ssa::traits::*; -use rustc::ty::layout::{self, Size, Align, AbiAndPrefAlign, LayoutOf}; +use rustc::ty::layout::{self, Size, Align, LayoutOf}; use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags}; @@ -89,20 +89,20 @@ pub fn codegen_static_initializer( fn set_global_alignment(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, - mut align: AbiAndPrefAlign) { + mut align: Align) { // The target may require greater alignment for globals than the type does. // Note: GCC and Clang also allow `__attribute__((aligned))` on variables, // which can force it to be smaller. Rust doesn't support this yet. if let Some(min) = cx.sess().target.target.options.min_global_align { match Align::from_bits(min) { - Ok(min) => align = align.max(AbiAndPrefAlign::new(min)), + Ok(min) => align = align.max(min), Err(err) => { cx.sess().err(&format!("invalid minimum global alignment: {}", err)); } } } unsafe { - llvm::LLVMSetAlignment(gv, align.abi.bytes() as u32); + llvm::LLVMSetAlignment(gv, align.bytes() as u32); } } @@ -186,7 +186,7 @@ impl StaticMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn static_addr_of_mut( &self, cv: &'ll Value, - align: AbiAndPrefAlign, + align: Align, kind: Option<&str>, ) -> &'ll Value { unsafe { @@ -212,14 +212,14 @@ impl StaticMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn static_addr_of( &self, cv: &'ll Value, - align: AbiAndPrefAlign, + align: Align, kind: Option<&str>, ) -> &'ll Value { if let Some(&gv) = self.const_globals.borrow().get(&cv) { unsafe { // Upgrade the alignment in cases where the same constant is used with different // alignment requirements - let llalign = align.abi.bytes() as u32; + let llalign = align.bytes() as u32; if llalign > llvm::LLVMGetAlignment(gv) { llvm::LLVMSetAlignment(gv, llalign); } diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 4cee3957042..81f2769800d 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -35,7 +35,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc::ty::Instance; use common::CodegenCx; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; -use rustc::ty::layout::{self, AbiAndPrefAlign, HasDataLayout, Integer, IntegerExt, LayoutOf, +use rustc::ty::layout::{self, Align, HasDataLayout, Integer, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout}; use rustc::session::config; use rustc::util::nodemap::FxHashMap; @@ -323,7 +323,7 @@ fn fixed_vec_metadata( llvm::LLVMRustDIBuilderCreateArrayType( DIB(cx), size.bits(), - align.abi.bits() as u32, + align.bits() as u32, element_type_metadata, subscripts) }; @@ -465,7 +465,7 @@ fn trait_pointer_metadata( syntax_pos::DUMMY_SP), offset: layout.fields.offset(0), size: data_ptr_field.size, - align: data_ptr_field.align, + align: data_ptr_field.align.abi, flags: DIFlags::FlagArtificial, discriminant: None, }, @@ -474,7 +474,7 @@ fn trait_pointer_metadata( type_metadata: type_metadata(cx, vtable_field.ty, syntax_pos::DUMMY_SP), offset: layout.fields.offset(1), size: vtable_field.size, - align: vtable_field.align, + align: vtable_field.align.abi, flags: DIFlags::FlagArtificial, discriminant: None, }, @@ -787,7 +787,7 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { DIB(cx), name.as_ptr(), size.bits(), - align.abi.bits() as u32, + align.bits() as u32, encoding) }; @@ -818,7 +818,7 @@ fn pointer_type_metadata( DIB(cx), pointee_type_metadata, pointer_size.bits(), - pointer_align.abi.bits() as u32, + pointer_align.bits() as u32, name.as_ptr()) } } @@ -923,7 +923,7 @@ struct MemberDescription<'ll> { type_metadata: &'ll DIType, offset: Size, size: Size, - align: AbiAndPrefAlign, + align: Align, flags: DIFlags, discriminant: Option, } @@ -990,7 +990,7 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> { type_metadata: type_metadata(cx, field.ty, self.span), offset: layout.fields.offset(i), size: field.size, - align: field.align, + align: field.align.abi, flags: DIFlags::FlagZero, discriminant: None, } @@ -1113,7 +1113,7 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> { type_metadata: type_metadata(cx, field.ty, self.span), offset: Size::ZERO, size: field.size, - align: field.align, + align: field.align.abi, flags: DIFlags::FlagZero, discriminant: None, } @@ -1226,7 +1226,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { type_metadata: variant_type_metadata, offset: Size::ZERO, size: self.layout.size, - align: self.layout.align, + align: self.layout.align.abi, flags: DIFlags::FlagZero, discriminant: None, } @@ -1265,7 +1265,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { type_metadata: variant_type_metadata, offset: Size::ZERO, size: self.layout.size, - align: self.layout.align, + align: self.layout.align.abi, flags: DIFlags::FlagZero, discriminant: Some(self.layout.ty.ty_adt_def().unwrap() .discriminant_for_variant(cx.tcx, i) @@ -1334,7 +1334,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { type_metadata: variant_type_metadata, offset: Size::ZERO, size: variant.size, - align: variant.align, + align: variant.align.abi, flags: DIFlags::FlagZero, discriminant: None, } @@ -1372,7 +1372,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { type_metadata: variant_type_metadata, offset: Size::ZERO, size: self.layout.size, - align: self.layout.align, + align: self.layout.align.abi, flags: DIFlags::FlagZero, discriminant: niche_value, } @@ -1675,7 +1675,7 @@ fn prepare_enum_metadata( file_metadata, UNKNOWN_LINE_NUMBER, size.bits(), - align.abi.bits() as u32, + align.bits() as u32, layout.fields.offset(0).bits(), DIFlags::FlagArtificial, discr_metadata)) @@ -1803,7 +1803,7 @@ fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>, unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, member_description.size.bits(), - member_description.align.abi.bits() as u32, + member_description.align.bits() as u32, member_description.offset.bits(), match member_description.discriminant { None => None, @@ -1851,7 +1851,7 @@ fn create_struct_stub( unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, struct_size.bits(), - struct_align.abi.bits() as u32, + struct_align.bits() as u32, DIFlags::FlagZero, None, empty_array, @@ -1889,7 +1889,7 @@ fn create_union_stub( unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, union_size.bits(), - union_align.abi.bits() as u32, + union_align.bits() as u32, DIFlags::FlagZero, Some(empty_array), 0, // RuntimeLang @@ -1958,7 +1958,7 @@ pub fn create_global_var_metadata( is_local_to_unit, global, None, - global_align.abi.bytes() as u32, + global_align.bytes() as u32, ); } } diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 199402982c6..e200da2b090 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -201,7 +201,7 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { cx.sess().opts.optimize != config::OptLevel::No, DIFlags::FlagZero, argument_index, - align.abi.bytes() as u32, + align.bytes() as u32, ) }; source_loc::set_debug_location(self, diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 1756fd5b0b1..3548ccfd5a5 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -110,7 +110,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let name = &*tcx.item_name(def_id).as_str(); let llret_ty = self.cx().layout_of(ret_ty).llvm_type(self.cx()); - let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout, fn_ty.ret.layout.align); + let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout, fn_ty.ret.layout.align.abi); let simple = get_simple_intrinsic(self.cx(), name); let llval = match name { @@ -158,7 +158,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { } "min_align_of" => { let tp_ty = substs.type_at(0); - self.cx().const_usize(self.cx().align_of(tp_ty).abi.bytes()) + self.cx().const_usize(self.cx().align_of(tp_ty).bytes()) } "min_align_of_val" => { let tp_ty = substs.type_at(0); @@ -167,12 +167,12 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { glue::size_and_align_of_dst(self, tp_ty, Some(meta)); llalign } else { - self.cx().const_usize(self.cx().align_of(tp_ty).abi.bytes()) + self.cx().const_usize(self.cx().align_of(tp_ty).bytes()) } } "pref_align_of" => { let tp_ty = substs.type_at(0); - self.cx().const_usize(self.cx().align_of(tp_ty).pref.bytes()) + self.cx().const_usize(self.cx().layout_of(tp_ty).align.pref.bytes()) } "type_name" => { let tp_ty = substs.type_at(0); @@ -261,7 +261,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let align = if name == "unaligned_volatile_load" { 1 } else { - self.cx().align_of(tp_ty).abi.bytes() as u32 + self.cx().align_of(tp_ty).bytes() as u32 }; unsafe { llvm::LLVMSetAlignment(load, align); @@ -815,7 +815,7 @@ fn try_intrinsic( ) { if bx.cx().sess().no_landing_pads() { bx.call(func, &[data], None); - let ptr_align = bx.tcx().data_layout.pointer_align; + let ptr_align = bx.tcx().data_layout.pointer_align.abi; bx.store(bx.cx().const_null(bx.cx().type_i8p()), dest, ptr_align); } else if wants_msvc_seh(bx.cx().sess()) { codegen_msvc_try(bx, func, data, local_ptr, dest); @@ -890,7 +890,7 @@ fn codegen_msvc_try( // // More information can be found in libstd's seh.rs implementation. let i64p = bx.cx().type_ptr_to(bx.cx().type_i64()); - let ptr_align = bx.tcx().data_layout.pointer_align; + let ptr_align = bx.tcx().data_layout.pointer_align.abi; let slot = bx.alloca(i64p, "slot", ptr_align); bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None); @@ -906,7 +906,7 @@ fn codegen_msvc_try( let funclet = catchpad.catch_pad(cs, &[tydesc, bx.cx().const_i32(0), slot]); let addr = catchpad.load(slot, ptr_align); - let i64_align = bx.tcx().data_layout.i64_align; + let i64_align = bx.tcx().data_layout.i64_align.abi; let arg1 = catchpad.load(addr, i64_align); let val1 = bx.cx().const_i32(1); let gep1 = catchpad.inbounds_gep(addr, &[val1]); @@ -923,7 +923,7 @@ fn codegen_msvc_try( // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). let ret = bx.call(llfn, &[func, data, local_ptr], None); - let i32_align = bx.tcx().data_layout.i32_align; + let i32_align = bx.tcx().data_layout.i32_align.abi; bx.store(ret, dest, i32_align); } @@ -982,7 +982,7 @@ fn codegen_gnu_try( let vals = catch.landing_pad(lpad_ty, bx.cx().eh_personality(), 1); catch.add_clause(vals, bx.cx().const_null(bx.cx().type_i8p())); let ptr = catch.extract_value(vals, 0); - let ptr_align = bx.tcx().data_layout.pointer_align; + let ptr_align = bx.tcx().data_layout.pointer_align.abi; let bitcast = catch.bitcast(local_ptr, bx.cx().type_ptr_to(bx.cx().type_i8p())); catch.store(ptr, bitcast, ptr_align); catch.ret(bx.cx().const_i32(1)); @@ -991,7 +991,7 @@ fn codegen_gnu_try( // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). let ret = bx.call(llfn, &[func, data, local_ptr], None); - let i32_align = bx.tcx().data_layout.i32_align; + let i32_align = bx.tcx().data_layout.i32_align.abi; bx.store(ret, dest, i32_align); } @@ -1436,7 +1436,7 @@ fn generic_simd_intrinsic( // Alignment of T, must be a constant integer value: let alignment_ty = bx.cx().type_i32(); - let alignment = bx.cx().const_i32(bx.cx().align_of(in_elem).abi.bytes() as i32); + let alignment = bx.cx().const_i32(bx.cx().align_of(in_elem).bytes() as i32); // Truncate the mask vector to a vector of i1s: let (mask, mask_ty) = { @@ -1536,7 +1536,7 @@ fn generic_simd_intrinsic( // Alignment of T, must be a constant integer value: let alignment_ty = bx.cx().type_i32(); - let alignment = bx.cx().const_i32(bx.cx().align_of(in_elem).abi.bytes() as i32); + let alignment = bx.cx().const_i32(bx.cx().align_of(in_elem).bytes() as i32); // Truncate the mask vector to a vector of i1s: let (mask, mask_ty) = { diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 8ce3be36d0b..15b5bdeb44d 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -12,7 +12,7 @@ use abi::{FnType, FnTypeExt}; use common::*; use rustc::hir; use rustc::ty::{self, Ty, TypeFoldable}; -use rustc::ty::layout::{self, AbiAndPrefAlign, LayoutOf, Size, TyLayout}; +use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout}; use rustc_target::abi::FloatTy; use rustc_mir::monomorphize::item::DefPathBasedNames; use type_::Type; @@ -80,7 +80,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, match layout.fields { layout::FieldPlacement::Union(_) => { - let fill = cx.type_padding_filler(layout.size, layout.align); + let fill = cx.type_padding_filler(layout.size, layout.align.abi); let packed = false; match name { None => { @@ -120,23 +120,23 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let mut packed = false; let mut offset = Size::ZERO; - let mut prev_effective_align = layout.align; + let mut prev_effective_align = layout.align.abi; let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2); for i in layout.fields.index_by_increasing_offset() { let target_offset = layout.fields.offset(i as usize); let field = layout.field(cx, i); - let effective_field_align = AbiAndPrefAlign::new(layout.align.abi + let effective_field_align = layout.align.abi .min(field.align.abi) - .restrict_for_offset(target_offset)); - packed |= effective_field_align.abi < field.align.abi; + .restrict_for_offset(target_offset); + packed |= effective_field_align < field.align.abi; debug!("struct_llfields: {}: {:?} offset: {:?} target_offset: {:?} \ effective_field_align: {}", - i, field, offset, target_offset, effective_field_align.abi.bytes()); + i, field, offset, target_offset, effective_field_align.bytes()); assert!(target_offset >= offset); let padding = target_offset - offset; let padding_align = prev_effective_align.min(effective_field_align); - assert_eq!(offset.abi_align(padding_align) + padding, target_offset); + assert_eq!(offset.align_to(padding_align) + padding, target_offset); result.push(cx.type_padding_filler( padding, padding_align)); debug!(" padding before: {:?}", padding); @@ -151,7 +151,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } let padding = layout.size - offset; let padding_align = prev_effective_align; - assert_eq!(offset.abi_align(padding_align) + padding, layout.size); + assert_eq!(offset.align_to(padding_align) + padding, layout.size); debug!("struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}", padding, offset, layout.size); result.push(cx.type_padding_filler(padding, padding_align)); @@ -165,17 +165,17 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } impl<'a, 'tcx> CodegenCx<'a, 'tcx> { - pub fn align_of(&self, ty: Ty<'tcx>) -> AbiAndPrefAlign { - self.layout_of(ty).align + pub fn align_of(&self, ty: Ty<'tcx>) -> Align { + self.layout_of(ty).align.abi } pub fn size_of(&self, ty: Ty<'tcx>) -> Size { self.layout_of(ty).size } - pub fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, AbiAndPrefAlign) { + pub fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, Align) { let layout = self.layout_of(ty); - (layout.size, layout.align) + (layout.size, layout.align.abi) } } @@ -197,7 +197,7 @@ pub enum PointerKind { #[derive(Copy, Clone)] pub struct PointeeInfo { pub size: Size, - pub align: AbiAndPrefAlign, + pub align: Align, pub safe: Option, } @@ -333,7 +333,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { layout::Pointer => { // If we know the alignment, pick something better than i8. let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) { - cx.type_pointee_for_abi_align( pointee.align) + cx.type_pointee_for_align(pointee.align) } else { cx.type_i8() }; @@ -377,7 +377,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { let offset = if index == 0 { Size::ZERO } else { - a.value.size(cx).abi_align(b.value.align(cx)) + a.value.size(cx).align_to(b.value.align(cx).abi) }; self.scalar_llvm_type_at(cx, scalar, offset) } diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index e80ff8b6580..856bb9533c8 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -31,7 +31,7 @@ use rustc::middle::lang_items::StartFnLangItem; use rustc::middle::weak_lang_items; use rustc::mir::mono::{Stats, CodegenUnitNameBuilder}; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::{self, AbiAndPrefAlign, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; +use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::ty::query::Providers; use rustc::middle::cstore::{self, LinkagePreference}; use rustc::util::common::{time, print_time_passes_entry}; @@ -410,9 +410,9 @@ pub fn to_immediate_scalar<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( pub fn memcpy_ty<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, dst: Bx::Value, - dst_align: AbiAndPrefAlign, + dst_align: Align, src: Bx::Value, - src_align: AbiAndPrefAlign, + src_align: Align, layout: TyLayout<'tcx>, flags: MemFlags, ) { diff --git a/src/librustc_codegen_ssa/meth.rs b/src/librustc_codegen_ssa/meth.rs index 60268533c85..e45cccee349 100644 --- a/src/librustc_codegen_ssa/meth.rs +++ b/src/librustc_codegen_ssa/meth.rs @@ -41,7 +41,7 @@ impl<'a, 'tcx: 'a> VirtualIndex { llvtable, bx.cx().type_ptr_to(bx.cx().fn_ptr_backend_type(fn_ty)) ); - let ptr_align = bx.tcx().data_layout.pointer_align; + let ptr_align = bx.tcx().data_layout.pointer_align.abi; let gep = bx.inbounds_gep(llvtable, &[bx.cx().const_usize(self.0)]); let ptr = bx.load(gep, ptr_align); bx.nonnull_metadata(ptr); @@ -59,7 +59,7 @@ impl<'a, 'tcx: 'a> VirtualIndex { debug!("get_int({:?}, {:?})", llvtable, self); let llvtable = bx.pointercast(llvtable, bx.cx().type_ptr_to(bx.cx().type_isize())); - let usize_align = bx.tcx().data_layout.pointer_align; + let usize_align = bx.tcx().data_layout.pointer_align.abi; let gep = bx.inbounds_gep(llvtable, &[bx.cx().const_usize(self.0)]); let ptr = bx.load(gep, usize_align); // Vtable loads are invariant @@ -112,7 +112,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( ].iter().cloned().chain(methods).collect(); let vtable_const = cx.const_struct(&components, false); - let align = cx.data_layout().pointer_align; + let align = cx.data_layout().pointer_align.abi; let vtable = cx.static_addr_of(vtable_const, align, Some("vtable")); cx.create_vtable_metadata(ty, vtable); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 693addd441f..75a6f07124a 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -280,7 +280,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { scratch.llval } Ref(llval, _, align) => { - assert_eq!(align.abi, op.layout.align.abi, + assert_eq!(align, op.layout.align.abi, "return place is unaligned!"); llval } @@ -288,7 +288,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let addr = bx.pointercast(llslot, bx.cx().type_ptr_to( bx.cx().cast_backend_type(&cast_ty) )); - bx.load(addr, self.fn_ty.ret.layout.align) + bx.load(addr, self.fn_ty.ret.layout.align.abi) } }; bx.ret(llval); @@ -386,9 +386,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let filename = bx.cx().const_str_slice(filename); let line = bx.cx().const_u32(loc.line as u32); let col = bx.cx().const_u32(loc.col.to_usize() as u32 + 1); - let align = tcx.data_layout.aggregate_align - .max(tcx.data_layout.i32_align) - .max(tcx.data_layout.pointer_align); + let align = tcx.data_layout.aggregate_align.abi + .max(tcx.data_layout.i32_align.abi) + .max(tcx.data_layout.pointer_align.abi); // Put together the arguments to the panic entry point. let (lang_item, args) = match *msg { @@ -522,9 +522,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let filename = bx.cx().const_str_slice(filename); let line = bx.cx().const_u32(loc.line as u32); let col = bx.cx().const_u32(loc.col.to_usize() as u32 + 1); - let align = tcx.data_layout.aggregate_align - .max(tcx.data_layout.i32_align) - .max(tcx.data_layout.pointer_align); + let align = tcx.data_layout.aggregate_align.abi + .max(tcx.data_layout.i32_align.abi) + .max(tcx.data_layout.pointer_align.abi); let str = format!( "Attempted to instantiate uninhabited type {} using mem::{}", @@ -800,12 +800,12 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (scratch.llval, scratch.align, true) } _ => { - (op.immediate_or_packed_pair(bx), arg.layout.align, false) + (op.immediate_or_packed_pair(bx), arg.layout.align.abi, false) } } } Ref(llval, _, align) => { - if arg.is_indirect() && align.abi < arg.layout.align.abi { + if arg.is_indirect() && align < arg.layout.align.abi { // `foo(packed.large_field)`. We can't pass the (unaligned) field directly. I // think that ATM (Rust 1.16) we only pass temporaries, but we shouldn't // have scary latent bugs around. @@ -826,7 +826,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let addr = bx.pointercast(llval, bx.cx().type_ptr_to( bx.cx().cast_backend_type(&ty)) ); - llval = bx.load(addr, align.min(arg.layout.align)); + llval = bx.load(addr, align.min(arg.layout.align.abi)); } else { // We can't use `PlaceRef::load` here because the argument // may have a type we don't treat as immediate, but the ABI @@ -1006,7 +1006,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_place(bx, dest) }; if fn_ret.is_indirect() { - if dest.align.abi < dest.layout.align.abi { + if dest.align < dest.layout.align.abi { // Currently, MIR code generation does not create calls // that store directly to fields of packed structs (in // fact, the calls it creates write only to temps), @@ -1062,7 +1062,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let src = self.codegen_operand(bx, src); let llty = bx.cx().backend_type(src.layout); let cast_ptr = bx.pointercast(dst.llval, bx.cx().type_ptr_to(llty)); - let align = src.layout.align.min(dst.layout.align); + let align = src.layout.align.abi.min(dst.align); src.val.store(bx, PlaceRef::new_sized(cast_ptr, src.layout, align)); } diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 0579afe1d49..fdc9a37a9eb 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -304,7 +304,7 @@ pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( if local == mir::RETURN_PLACE && fx.fn_ty.ret.is_indirect() { debug!("alloc: {:?} (return place) -> place", local); let llretptr = fx.cx.get_param(llfn, 0); - LocalRef::Place(PlaceRef::new_sized(llretptr, layout, layout.align)) + LocalRef::Place(PlaceRef::new_sized(llretptr, layout, layout.align.abi)) } else if memory_locals.contains(local) { debug!("alloc: {:?} -> place", local); if layout.is_unsized() { @@ -555,7 +555,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( let llarg = bx.cx().get_param(bx.llfn(), llarg_idx as c_uint); bx.set_value_name(llarg, &name); llarg_idx += 1; - PlaceRef::new_sized(llarg, arg.layout, arg.layout.align) + PlaceRef::new_sized(llarg, arg.layout, arg.layout.align.abi) } else if arg.is_unsized_indirect() { // As the storage for the indirect argument lives during // the whole function call, we just copy the fat pointer. diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index c604386456c..f6917906d4a 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -11,7 +11,7 @@ use rustc::mir::interpret::{ConstValue, ErrorHandled}; use rustc::mir; use rustc::ty; -use rustc::ty::layout::{self, Align, AbiAndPrefAlign, LayoutOf, TyLayout}; +use rustc::ty::layout::{self, Align, LayoutOf, TyLayout}; use base; use MemFlags; @@ -33,7 +33,7 @@ pub enum OperandValue { /// to be valid for the operand's lifetime. /// The second value, if any, is the extra data (vtable or length) /// which indicates that it refers to an unsized rvalue. - Ref(V, Option, AbiAndPrefAlign), + Ref(V, Option, Align), /// A single LLVM value. Immediate(V), /// A pair of immediate LLVM values. Used by fat pointers too. @@ -152,7 +152,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> { llval: llptr, llextra, layout, - align: layout.align, + align: layout.align.abi, } } @@ -228,7 +228,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> { OperandValue::Immediate(a_llval) } else { assert_eq!(offset, a.value.size(bx.cx()) - .abi_align(b.value.align(bx.cx()))); + .align_to(b.value.align(bx.cx()).abi)); assert_eq!(field.size, b.value.size(bx.cx())); OperandValue::Immediate(b_llval) } @@ -348,8 +348,8 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandValue { }; // FIXME: choose an appropriate alignment, or use dynamic align somehow - let max_align = AbiAndPrefAlign::new(Align::from_bits(128).unwrap()); - let min_align = AbiAndPrefAlign::new(Align::from_bits(8).unwrap()); + let max_align = Align::from_bits(128).unwrap(); + let min_align = Align::from_bits(8).unwrap(); // Allocate an appropriate region on the stack, and copy the value into it let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra)); @@ -470,7 +470,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.load_operand(PlaceRef::new_sized( bx.cx().const_undef(bx.cx().type_ptr_to(bx.cx().backend_type(layout))), layout, - layout.align, + layout.align.abi, )) }) } diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index f78f7a50561..e6fd6dfca73 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -9,7 +9,7 @@ // except according to those terms. use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, AbiAndPrefAlign, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; +use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::mir; use rustc::mir::tcx::PlaceTy; use MemFlags; @@ -33,14 +33,14 @@ pub struct PlaceRef<'tcx, V> { pub layout: TyLayout<'tcx>, /// What alignment we know for this place - pub align: AbiAndPrefAlign, + pub align: Align, } impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { pub fn new_sized( llval: V, layout: TyLayout<'tcx>, - align: AbiAndPrefAlign, + align: Align, ) -> PlaceRef<'tcx, V> { assert!(!layout.is_unsized()); PlaceRef { @@ -58,8 +58,8 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { ) -> Self { debug!("alloca({:?}: {:?})", name, layout); assert!(!layout.is_unsized(), "tried to statically allocate unsized place"); - let tmp = bx.alloca(bx.cx().backend_type(layout), name, layout.align); - Self::new_sized(tmp, layout, layout.align) + let tmp = bx.alloca(bx.cx().backend_type(layout), name, layout.align.abi); + Self::new_sized(tmp, layout, layout.align.abi) } /// Returns a place for an indirect reference to an unsized place. @@ -101,7 +101,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { ) -> Self { let field = self.layout.field(bx.cx(), ix); let offset = self.layout.fields.offset(ix); - let effective_field_align = self.align.abi.restrict_for_offset(offset); + let effective_field_align = self.align.restrict_for_offset(offset); let mut simple = || { // Unions and newtypes only use an offset of 0. @@ -109,7 +109,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { self.llval } else if let layout::Abi::ScalarPair(ref a, ref b) = self.layout.abi { // Offsets have to match either first or second field. - assert_eq!(offset, a.value.size(bx.cx()).abi_align(b.value.align(bx.cx()))); + assert_eq!(offset, a.value.size(bx.cx()).align_to(b.value.align(bx.cx()).abi)); bx.struct_gep(self.llval, 1) } else { bx.struct_gep(self.llval, bx.cx().backend_field_index(self.layout, ix)) @@ -123,7 +123,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { None }, layout: field, - align: AbiAndPrefAlign::new(effective_field_align), + align: effective_field_align, } }; @@ -197,7 +197,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { llval: bx.pointercast(byte_ptr, bx.cx().type_ptr_to(ll_fty)), llextra: self.llextra, layout: field, - align: AbiAndPrefAlign::new(effective_field_align), + align: effective_field_align, } } @@ -418,13 +418,13 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llval = bx.cx().const_undef( bx.cx().type_ptr_to(bx.cx().backend_type(layout)) ); - PlaceRef::new_sized(llval, layout, layout.align) + PlaceRef::new_sized(llval, layout, layout.align.abi) } } } mir::Place::Static(box mir::Static { def_id, ty }) => { let layout = cx.layout_of(self.monomorphize(&ty)); - PlaceRef::new_sized(cx.get_static(def_id), layout, layout.align) + PlaceRef::new_sized(cx.get_static(def_id), layout, layout.align.abi) }, mir::Place::Projection(box mir::Projection { ref base, diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs index 02be098599b..0b3066f561c 100644 --- a/src/librustc_codegen_ssa/traits/builder.rs +++ b/src/librustc_codegen_ssa/traits/builder.rs @@ -17,7 +17,7 @@ use super::HasCodegen; use common::{AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope}; use mir::operand::OperandRef; use mir::place::PlaceRef; -use rustc::ty::layout::{AbiAndPrefAlign, Size}; +use rustc::ty::layout::{Align, Size}; use std::ffi::CStr; use MemFlags; @@ -97,18 +97,17 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: fn fneg(&mut self, v: Self::Value) -> Self::Value; fn not(&mut self, v: Self::Value) -> Self::Value; - fn alloca(&mut self, ty: Self::Type, name: &str, align: AbiAndPrefAlign) -> Self::Value; - fn dynamic_alloca(&mut self, ty: Self::Type, name: &str, align: AbiAndPrefAlign) - -> Self::Value; + fn alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value; + fn dynamic_alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value; fn array_alloca( &mut self, ty: Self::Type, len: Self::Value, name: &str, - align: AbiAndPrefAlign, + align: Align, ) -> Self::Value; - fn load(&mut self, ptr: Self::Value, align: AbiAndPrefAlign) -> Self::Value; + fn load(&mut self, ptr: Self::Value, align: Align) -> Self::Value; fn volatile_load(&mut self, ptr: Self::Value) -> Self::Value; fn atomic_load(&mut self, ptr: Self::Value, order: AtomicOrdering, size: Size) -> Self::Value; fn load_operand(&mut self, place: PlaceRef<'tcx, Self::Value>) @@ -117,12 +116,12 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: fn range_metadata(&mut self, load: Self::Value, range: Range); fn nonnull_metadata(&mut self, load: Self::Value); - fn store(&mut self, val: Self::Value, ptr: Self::Value, align: AbiAndPrefAlign) -> Self::Value; + fn store(&mut self, val: Self::Value, ptr: Self::Value, align: Align) -> Self::Value; fn store_with_flags( &mut self, val: Self::Value, ptr: Self::Value, - align: AbiAndPrefAlign, + align: Align, flags: MemFlags, ) -> Self::Value; fn atomic_store( @@ -175,18 +174,18 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: fn memcpy( &mut self, dst: Self::Value, - dst_align: AbiAndPrefAlign, + dst_align: Align, src: Self::Value, - src_align: AbiAndPrefAlign, + src_align: Align, size: Self::Value, flags: MemFlags, ); fn memmove( &mut self, dst: Self::Value, - dst_align: AbiAndPrefAlign, + dst_align: Align, src: Self::Value, - src_align: AbiAndPrefAlign, + src_align: Align, size: Self::Value, flags: MemFlags, ); @@ -195,7 +194,7 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: ptr: Self::Value, fill_byte: Self::Value, size: Self::Value, - align: AbiAndPrefAlign, + align: Align, flags: MemFlags, ); diff --git a/src/librustc_codegen_ssa/traits/statics.rs b/src/librustc_codegen_ssa/traits/statics.rs index b66f4378c35..172c48f8a85 100644 --- a/src/librustc_codegen_ssa/traits/statics.rs +++ b/src/librustc_codegen_ssa/traits/statics.rs @@ -10,23 +10,13 @@ use super::Backend; use rustc::hir::def_id::DefId; -use rustc::ty::layout::AbiAndPrefAlign; +use rustc::ty::layout::Align; pub trait StaticMethods<'tcx>: Backend<'tcx> { fn static_ptrcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value; fn static_bitcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value; - fn static_addr_of_mut( - &self, - cv: Self::Value, - align: AbiAndPrefAlign, - kind: Option<&str>, - ) -> Self::Value; - fn static_addr_of( - &self, - cv: Self::Value, - align: AbiAndPrefAlign, - kind: Option<&str>, - ) -> Self::Value; + fn static_addr_of_mut(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value; + fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value; fn get_static(&self, def_id: DefId) -> Self::Value; fn codegen_static(&self, def_id: DefId, is_mutable: bool); unsafe fn static_replace_all_uses(&self, old_g: Self::Value, new_g: Self::Value); diff --git a/src/librustc_codegen_ssa/traits/type_.rs b/src/librustc_codegen_ssa/traits/type_.rs index 275f378495d..15976ac516d 100644 --- a/src/librustc_codegen_ssa/traits/type_.rs +++ b/src/librustc_codegen_ssa/traits/type_.rs @@ -13,7 +13,7 @@ use super::Backend; use super::HasCodegen; use common::{self, TypeKind}; use mir::place::PlaceRef; -use rustc::ty::layout::{self, AbiAndPrefAlign, Size, TyLayout}; +use rustc::ty::layout::{self, Align, Size, TyLayout}; use rustc::ty::{self, Ty}; use rustc::util::nodemap::FxHashMap; use rustc_target::abi::call::{ArgType, CastTarget, FnType, Reg}; @@ -120,16 +120,16 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { } } - fn type_pointee_for_abi_align(&self, align: AbiAndPrefAlign) -> Self::Type { + fn type_pointee_for_align(&self, align: Align) -> Self::Type { // FIXME(eddyb) We could find a better approximation if ity.align < align. - let ity = layout::Integer::approximate_abi_align(self, align); + let ity = layout::Integer::approximate_align(self, align); self.type_from_integer(ity) } /// Return a LLVM type that has at most the required alignment, /// and exactly the required size, as a best-effort padding array. - fn type_padding_filler(&self, size: Size, align: AbiAndPrefAlign) -> Self::Type { - let unit = layout::Integer::approximate_abi_align(self, align); + fn type_padding_filler(&self, size: Size, align: Align) -> Self::Type { + let unit = layout::Integer::approximate_align(self, align); let size = size.bytes(); let unit_size = unit.size().bytes(); assert_eq!(size % unit_size, 0); diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 6a8a9fe817c..1bc3b322717 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -129,7 +129,7 @@ pub fn op_to_const<'tcx>( assert!(meta.is_none()); let ptr = ptr.to_ptr()?; let alloc = ecx.memory.get(ptr.alloc_id)?; - assert!(alloc.align.abi >= align.abi); + assert!(alloc.align >= align); assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= op.layout.size.bytes()); let mut alloc = alloc.clone(); alloc.align = align; diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index b3e9008a6b7..936b476df39 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -16,7 +16,7 @@ use rustc::hir::def_id::DefId; use rustc::hir::def::Def; use rustc::mir; use rustc::ty::layout::{ - self, Size, AbiAndPrefAlign, HasDataLayout, LayoutOf, TyLayout + self, Size, Align, HasDataLayout, LayoutOf, TyLayout }; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -314,9 +314,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc &self, metadata: Option>, layout: TyLayout<'tcx>, - ) -> EvalResult<'tcx, Option<(Size, AbiAndPrefAlign)>> { + ) -> EvalResult<'tcx, Option<(Size, Align)>> { if !layout.is_unsized() { - return Ok(Some((layout.size, layout.align))); + return Ok(Some((layout.size, layout.align.abi))); } match layout.ty.sty { ty::Adt(..) | ty::Tuple(..) => { @@ -328,7 +328,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc trace!("DST layout: {:?}", layout); let sized_size = layout.fields.offset(layout.fields.count() - 1); - let sized_align = layout.align; + let sized_align = layout.align.abi; trace!( "DST {} statically sized prefix size: {:?} align: {:?}", layout.ty, @@ -381,7 +381,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc // // `(size + (align-1)) & -align` - Ok(Some((size.abi_align(align), align))) + Ok(Some((size.align_to(align), align))) } ty::Dynamic(..) => { let vtable = metadata.expect("dyn trait fat ptr must have vtable").to_ptr()?; @@ -392,7 +392,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc ty::Slice(_) | ty::Str => { let len = metadata.expect("slice fat ptr must have vtable").to_usize(self)?; let elem = layout.field(self, 0)?; - Ok(Some((elem.size * len, elem.align))) + Ok(Some((elem.size * len, elem.align.abi))) } ty::Foreign(_) => { @@ -406,7 +406,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc pub fn size_and_align_of_mplace( &self, mplace: MPlaceTy<'tcx, M::PointerTag> - ) -> EvalResult<'tcx, Option<(Size, AbiAndPrefAlign)>> { + ) -> EvalResult<'tcx, Option<(Size, Align)>> { self.size_and_align_of(mplace.meta, mplace.layout) } @@ -636,7 +636,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc let (ptr, align) = mplace.to_scalar_ptr_align(); match ptr { Scalar::Ptr(ptr) => { - write!(msg, " by align({}) ref:", align.abi.bytes()).unwrap(); + write!(msg, " by align({}) ref:", align.bytes()).unwrap(); allocs.push(ptr.alloc_id); } ptr => write!(msg, " by integral ref: {:?}", ptr).unwrap(), @@ -665,7 +665,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc Place::Ptr(mplace) => { match mplace.ptr { Scalar::Ptr(ptr) => { - trace!("by align({}) ref:", mplace.align.abi.bytes()); + trace!("by align({}) ref:", mplace.align.bytes()); self.memory.dump_alloc(ptr.alloc_id); } ptr => trace!(" integral by ref: {:?}", ptr), diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 681e7329754..898600d8322 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -21,7 +21,7 @@ use std::ptr; use std::borrow::Cow; use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt}; -use rustc::ty::layout::{self, Align, AbiAndPrefAlign, TargetDataLayout, Size, HasDataLayout}; +use rustc::ty::layout::{self, Align, TargetDataLayout, Size, HasDataLayout}; pub use rustc::mir::interpret::{truncate, write_target_uint, read_target_uint}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; @@ -71,7 +71,7 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { /// To be able to compare pointers with NULL, and to check alignment for accesses /// to ZSTs (where pointers may dangle), we keep track of the size even for allocations /// that do not exist any more. - dead_alloc_map: FxHashMap, + dead_alloc_map: FxHashMap, /// Lets us implement `HasDataLayout`, which is awfully convenient. pub(super) tcx: TyCtxtAt<'a, 'tcx, 'tcx>, @@ -130,7 +130,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn allocate( &mut self, size: Size, - align: AbiAndPrefAlign, + align: Align, kind: MemoryKind, ) -> EvalResult<'tcx, Pointer> { Ok(Pointer::from(self.allocate_with(Allocation::undef(size, align), kind)?)) @@ -140,9 +140,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &mut self, ptr: Pointer, old_size: Size, - old_align: AbiAndPrefAlign, + old_align: Align, new_size: Size, - new_align: AbiAndPrefAlign, + new_align: Align, kind: MemoryKind, ) -> EvalResult<'tcx, Pointer> { if ptr.offset.bytes() != 0 { @@ -179,7 +179,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn deallocate( &mut self, ptr: Pointer, - size_and_align: Option<(Size, AbiAndPrefAlign)>, + size_and_align: Option<(Size, Align)>, kind: MemoryKind, ) -> EvalResult<'tcx> { trace!("deallocating: {}", ptr.alloc_id); @@ -244,7 +244,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn check_align( &self, ptr: Scalar, - required_align: AbiAndPrefAlign + required_align: Align ) -> EvalResult<'tcx> { // Check non-NULL/Undef, extract offset let (offset, alloc_align) = match ptr { @@ -268,18 +268,18 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } }; // Check alignment - if alloc_align.abi < required_align.abi { + if alloc_align.bytes() < required_align.bytes() { return err!(AlignmentCheckFailed { has: alloc_align, required: required_align, }); } - if offset % required_align.abi.bytes() == 0 { + if offset % required_align.bytes() == 0 { Ok(()) } else { - let has = offset % required_align.abi.bytes(); + let has = offset % required_align.bytes(); err!(AlignmentCheckFailed { - has: AbiAndPrefAlign::new(Align::from_bytes(has).unwrap()), + has: Align::from_bytes(has).unwrap(), required: required_align, }) } @@ -443,22 +443,20 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } } - pub fn get_size_and_align(&self, id: AllocId) -> (Size, AbiAndPrefAlign) { + pub fn get_size_and_align(&self, id: AllocId) -> (Size, Align) { if let Ok(alloc) = self.get(id) { return (Size::from_bytes(alloc.bytes.len() as u64), alloc.align); } // Could also be a fn ptr or extern static match self.tcx.alloc_map.lock().get(id) { - Some(AllocType::Function(..)) => { - (Size::ZERO, AbiAndPrefAlign::new(Align::from_bytes(1).unwrap())) - } + Some(AllocType::Function(..)) => (Size::ZERO, Align::from_bytes(1).unwrap()), Some(AllocType::Static(did)) => { // The only way `get` couldn't have worked here is if this is an extern static assert!(self.tcx.is_foreign_item(did)); // Use size and align of the type let ty = self.tcx.type_of(did); let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); - (layout.size, layout.align) + (layout.size, layout.align.abi) } _ => { // Must be a deallocated pointer @@ -523,7 +521,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { "{}({} bytes, alignment {}){}", msg, alloc.bytes.len(), - alloc.align.abi.bytes(), + alloc.align.bytes(), extra ); @@ -624,7 +622,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &self, ptr: Pointer, size: Size, - align: AbiAndPrefAlign, + align: Align, check_defined_and_ptr: bool, ) -> EvalResult<'tcx, &[u8]> { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); @@ -653,7 +651,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &self, ptr: Pointer, size: Size, - align: AbiAndPrefAlign + align: Align ) -> EvalResult<'tcx, &[u8]> { self.get_bytes_internal(ptr, size, align, true) } @@ -665,7 +663,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &self, ptr: Pointer, size: Size, - align: AbiAndPrefAlign + align: Align ) -> EvalResult<'tcx, &[u8]> { self.get_bytes_internal(ptr, size, align, false) } @@ -676,7 +674,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &mut self, ptr: Pointer, size: Size, - align: AbiAndPrefAlign, + align: Align, ) -> EvalResult<'tcx, &mut [u8]> { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); self.check_align(ptr.into(), align)?; @@ -749,9 +747,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn copy( &mut self, src: Scalar, - src_align: AbiAndPrefAlign, + src_align: Align, dest: Scalar, - dest_align: AbiAndPrefAlign, + dest_align: Align, size: Size, nonoverlapping: bool, ) -> EvalResult<'tcx> { @@ -761,9 +759,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn copy_repeatedly( &mut self, src: Scalar, - src_align: AbiAndPrefAlign, + src_align: Align, dest: Scalar, - dest_align: AbiAndPrefAlign, + dest_align: Align, size: Size, length: u64, nonoverlapping: bool, @@ -865,7 +863,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { allow_ptr_and_undef: bool, ) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = AbiAndPrefAlign::new(Align::from_bytes(1).unwrap()); + let align = Align::from_bytes(1).unwrap(); if size.bytes() == 0 { self.check_align(ptr, align)?; return Ok(()); @@ -883,7 +881,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = AbiAndPrefAlign::new(Align::from_bytes(1).unwrap()); + let align = Align::from_bytes(1).unwrap(); if size.bytes() == 0 { self.check_align(ptr, align)?; return Ok(&[]); @@ -893,7 +891,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = AbiAndPrefAlign::new(Align::from_bytes(1).unwrap()); + let align = Align::from_bytes(1).unwrap(); if src.is_empty() { self.check_align(ptr, align)?; return Ok(()); @@ -910,7 +908,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { count: Size ) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = AbiAndPrefAlign::new(Align::from_bytes(1).unwrap()); + let align = Align::from_bytes(1).unwrap(); if count.bytes() == 0 { self.check_align(ptr, align)?; return Ok(()); @@ -926,7 +924,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn read_scalar( &self, ptr: Pointer, - ptr_align: AbiAndPrefAlign, + ptr_align: Align, size: Size ) -> EvalResult<'tcx, ScalarMaybeUndef> { // get_bytes_unchecked tests alignment and relocation edges @@ -963,7 +961,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn read_ptr_sized( &self, ptr: Pointer, - ptr_align: AbiAndPrefAlign + ptr_align: Align ) -> EvalResult<'tcx, ScalarMaybeUndef> { self.read_scalar(ptr, ptr_align, self.pointer_size()) } @@ -972,7 +970,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn write_scalar( &mut self, ptr: Pointer, - ptr_align: AbiAndPrefAlign, + ptr_align: Align, val: ScalarMaybeUndef, type_size: Size, ) -> EvalResult<'tcx> { @@ -1019,14 +1017,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn write_ptr_sized( &mut self, ptr: Pointer, - ptr_align: AbiAndPrefAlign, + ptr_align: Align, val: ScalarMaybeUndef ) -> EvalResult<'tcx> { let ptr_size = self.pointer_size(); self.write_scalar(ptr.into(), ptr_align, val, ptr_size) } - fn int_align(&self, size: Size) -> AbiAndPrefAlign { + fn int_align(&self, size: Size) -> Align { // We assume pointer-sized integers have the same alignment as pointers. // We also assume signed and unsigned integers of the same size have the same alignment. let ity = match size.bytes() { @@ -1037,7 +1035,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { 16 => layout::I128, _ => bug!("bad integer size: {}", size.bytes()), }; - ity.align(self) + ity.align(self).abi } } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 5d993cfee08..8238d580022 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -285,7 +285,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let (a, b) = (&a.value, &b.value); let (a_size, b_size) = (a.size(self), b.size(self)); let a_ptr = ptr; - let b_offset = a_size.abi_align(b.align(self)); + let b_offset = a_size.align_to(b.align(self).abi); assert!(b_offset.bytes() > 0); // we later use the offset to test which field to use let b_ptr = ptr.offset(b_offset, self)?.into(); let a_val = self.memory.read_scalar(a_ptr, ptr_align, a_size)?; diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index ed8b7cf1f90..7ef3dd5f720 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -18,8 +18,7 @@ use std::hash::Hash; use rustc::hir; use rustc::mir; use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, Size, Align, - AbiAndPrefAlign, LayoutOf, TyLayout, HasDataLayout, VariantIdx}; +use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx}; use super::{ GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic, @@ -33,7 +32,7 @@ pub struct MemPlace { /// be turned back into a reference before ever being dereferenced. /// However, it may never be undef. pub ptr: Scalar, - pub align: AbiAndPrefAlign, + pub align: Align, /// Metadata for unsized places. Interpretation is up to the type. /// Must not be present for sized types, but can be missing for unsized types /// (e.g. `extern type`). @@ -117,7 +116,7 @@ impl MemPlace { } #[inline(always)] - pub fn from_scalar_ptr(ptr: Scalar, align: AbiAndPrefAlign) -> Self { + pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self { MemPlace { ptr, align, @@ -128,17 +127,16 @@ impl MemPlace { /// Produces a Place that will error if attempted to be read from or written to #[inline(always)] pub fn null(cx: &impl HasDataLayout) -> Self { - Self::from_scalar_ptr(Scalar::ptr_null(cx), - AbiAndPrefAlign::new(Align::from_bytes(1).unwrap())) + Self::from_scalar_ptr(Scalar::ptr_null(cx), Align::from_bytes(1).unwrap()) } #[inline(always)] - pub fn from_ptr(ptr: Pointer, align: AbiAndPrefAlign) -> Self { + pub fn from_ptr(ptr: Pointer, align: Align) -> Self { Self::from_scalar_ptr(ptr.into(), align) } #[inline(always)] - pub fn to_scalar_ptr_align(self) -> (Scalar, AbiAndPrefAlign) { + pub fn to_scalar_ptr_align(self) -> (Scalar, Align) { assert!(self.meta.is_none()); (self.ptr, self.align) } @@ -170,7 +168,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> { MPlaceTy { mplace: MemPlace::from_scalar_ptr( Scalar::from_uint(layout.align.abi.bytes(), cx.pointer_size()), - layout.align + layout.align.abi ), layout } @@ -178,7 +176,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> { #[inline] fn from_aligned_ptr(ptr: Pointer, layout: TyLayout<'tcx>) -> Self { - MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align), layout } + MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align.abi), layout } } #[inline] @@ -232,12 +230,12 @@ impl<'tcx, Tag: ::std::fmt::Debug> Place { } #[inline(always)] - pub fn from_scalar_ptr(ptr: Scalar, align: AbiAndPrefAlign) -> Self { + pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self { Place::Ptr(MemPlace::from_scalar_ptr(ptr, align)) } #[inline(always)] - pub fn from_ptr(ptr: Pointer, align: AbiAndPrefAlign) -> Self { + pub fn from_ptr(ptr: Pointer, align: Align) -> Self { Place::Ptr(MemPlace::from_ptr(ptr, align)) } @@ -251,7 +249,7 @@ impl<'tcx, Tag: ::std::fmt::Debug> Place { } #[inline] - pub fn to_scalar_ptr_align(self) -> (Scalar, AbiAndPrefAlign) { + pub fn to_scalar_ptr_align(self) -> (Scalar, Align) { self.to_mem_place().to_scalar_ptr_align() } @@ -289,7 +287,7 @@ where let mplace = MemPlace { ptr: val.to_scalar_ptr()?, - align: layout.align, + align: layout.align.abi, meta: val.to_meta()?, }; Ok(MPlaceTy { mplace, layout }) @@ -358,11 +356,11 @@ where // FIXME: Once we have made decisions for how to handle size and alignment // of `extern type`, this should be adapted. It is just a temporary hack // to get some code to work that probably ought to work. - field_layout.align, + field_layout.align.abi, None => bug!("Cannot compute offset for extern type field at non-0 offset"), }; - (base.meta, offset.abi_align(align)) + (base.meta, offset.align_to(align)) } else { // base.meta could be present; we might be accessing a sized field of an unsized // struct. @@ -370,10 +368,10 @@ where }; let ptr = base.ptr.ptr_offset(offset, self)?; - let align = AbiAndPrefAlign::new(base.align.abi + let align = base.align // We do not look at `base.layout.align` nor `field_layout.align`, unlike // codegen -- mostly to see if we can get away with that - .restrict_for_offset(offset)); // must be last thing that happens + .restrict_for_offset(offset); // must be last thing that happens Ok(MPlaceTy { mplace: MemPlace { ptr, align, meta }, layout: field_layout }) } @@ -732,7 +730,7 @@ where } self.memory.write_scalar( - ptr, ptr_align.min(dest.layout.align), scalar, dest.layout.size + ptr, ptr_align.min(dest.layout.align.abi), scalar, dest.layout.size ) } Immediate::ScalarPair(a_val, b_val) => { @@ -742,8 +740,8 @@ where dest.layout) }; let (a_size, b_size) = (a.size(self), b.size(self)); - let (a_align, b_align) = (a.align(self), b.align(self)); - let b_offset = a_size.abi_align(b_align); + let (a_align, b_align) = (a.align(self).abi, b.align(self).abi); + let b_offset = a_size.align_to(b_align); let b_ptr = ptr.offset(b_offset, self)?.into(); // It is tempting to verify `b_offset` against `layout.fields.offset(1)`, @@ -901,7 +899,7 @@ where // FIXME: What should we do here? We should definitely also tag! Ok(MPlaceTy::dangling(layout, self)) } else { - let ptr = self.memory.allocate(layout.size, layout.align, kind)?; + let ptr = self.memory.allocate(layout.size, layout.align.abi, kind)?; let ptr = M::tag_new_allocation(self, ptr, kind)?; Ok(MPlaceTy::from_aligned_ptr(ptr, layout)) } @@ -1001,7 +999,7 @@ where let (size, align) = self.read_size_and_align_from_vtable(vtable)?; assert_eq!(size, layout.size); // only ABI alignment is preserved - assert_eq!(align.abi, layout.align.abi); + assert_eq!(align, layout.align.abi); } let mplace = MPlaceTy { diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs index 56475dffae4..4b63335ad96 100644 --- a/src/librustc_mir/interpret/snapshot.rs +++ b/src/librustc_mir/interpret/snapshot.rs @@ -16,7 +16,7 @@ use rustc::mir::interpret::{ }; use rustc::ty::{self, TyCtxt}; -use rustc::ty::layout::AbiAndPrefAlign; +use rustc::ty::layout::Align; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -276,7 +276,7 @@ struct AllocationSnapshot<'a> { bytes: &'a [u8], relocations: Relocations<(), AllocIdSnapshot<'a>>, undef_mask: &'a UndefMask, - align: &'a AbiAndPrefAlign, + align: &'a Align, mutability: &'a Mutability, } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 6070b31d3e7..fd17a4a7129 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -401,7 +401,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // cannot use the shim here, because that will only result in infinite recursion ty::InstanceDef::Virtual(_, idx) => { let ptr_size = self.pointer_size(); - let ptr_align = self.tcx.data_layout.pointer_align; + let ptr_align = self.tcx.data_layout.pointer_align.abi; let ptr = self.deref_operand(args[0])?; let vtable = ptr.vtable()?; let fn_ptr = self.memory.read_ptr_sized( diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index 02843b89812..f11fd45b753 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -9,7 +9,7 @@ // except according to those terms. use rustc::ty::{self, Ty}; -use rustc::ty::layout::{Size, Align, AbiAndPrefAlign, LayoutOf}; +use rustc::ty::layout::{Size, Align, LayoutOf}; use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic}; use super::{EvalContext, Machine, MemoryKind}; @@ -45,7 +45,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let align = layout.align.abi.bytes(); let ptr_size = self.pointer_size(); - let ptr_align = self.tcx.data_layout.pointer_align; + let ptr_align = self.tcx.data_layout.pointer_align.abi; // ///////////////////////////////////////////////////////////////////////////////////////// // If you touch this code, be sure to also make the corresponding changes to // `get_vtable` in rust_codegen_llvm/meth.rs @@ -87,7 +87,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> vtable: Pointer, ) -> EvalResult<'tcx, (ty::Instance<'tcx>, ty::Ty<'tcx>)> { // we don't care about the pointee type, we just want a pointer - let pointer_align = self.tcx.data_layout.pointer_align; + let pointer_align = self.tcx.data_layout.pointer_align.abi; let drop_fn = self.memory.read_ptr_sized(vtable, pointer_align)?.to_ptr()?; let drop_instance = self.memory.get_fn(drop_fn)?; trace!("Found drop fn: {:?}", drop_instance); @@ -101,15 +101,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> pub fn read_size_and_align_from_vtable( &self, vtable: Pointer, - ) -> EvalResult<'tcx, (Size, AbiAndPrefAlign)> { + ) -> EvalResult<'tcx, (Size, Align)> { let pointer_size = self.pointer_size(); - let pointer_align = self.tcx.data_layout.pointer_align; + let pointer_align = self.tcx.data_layout.pointer_align.abi; let size = self.memory.read_ptr_sized(vtable.offset(pointer_size, self)?,pointer_align)? .to_bits(pointer_size)? as u64; let align = self.memory.read_ptr_sized( vtable.offset(pointer_size * 2, self)?, pointer_align )?.to_bits(pointer_size)? as u64; - Ok((Size::from_bytes(size), AbiAndPrefAlign::new(Align::from_bytes(align).unwrap()))) + Ok((Size::from_bytes(size), Align::from_bytes(align).unwrap())) } } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 352569b3b64..6d1cacfa147 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -13,7 +13,7 @@ use std::hash::Hash; use std::ops::RangeInclusive; use syntax_pos::symbol::Symbol; -use rustc::ty::layout::{self, Size, Align, AbiAndPrefAlign, TyLayout, LayoutOf, VariantIdx}; +use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx}; use rustc::ty; use rustc_data_structures::fx::FxHashSet; use rustc::mir::interpret::{ @@ -355,7 +355,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> // for the purpose of validity, consider foreign types to have // alignment and size determined by the layout (size will be 0, // alignment should take attributes into account). - .unwrap_or_else(|| (layout.size, layout.align)); + .unwrap_or_else(|| (layout.size, layout.align.abi)); match self.ecx.memory.check_align(ptr, align) { Ok(_) => {}, Err(err) => { @@ -463,7 +463,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> // for function pointers. let non_null = self.ecx.memory.check_align( - Scalar::Ptr(ptr), AbiAndPrefAlign::new(Align::from_bytes(1).unwrap()) + Scalar::Ptr(ptr), Align::from_bytes(1).unwrap() ).is_ok() || self.ecx.memory.get_fn(ptr).is_ok(); if !non_null { diff --git a/src/librustc_target/abi/call/mips.rs b/src/librustc_target/abi/call/mips.rs index a40cb6c76f0..abe0bd07892 100644 --- a/src/librustc_target/abi/call/mips.rs +++ b/src/librustc_target/abi/call/mips.rs @@ -27,21 +27,21 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType, offset: &mut Size) { let dl = cx.data_layout(); let size = arg.layout.size; - let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align); + let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align).abi; if arg.layout.is_aggregate() { arg.cast_to(Uniform { unit: Reg::i32(), total: size }); - if !offset.is_abi_aligned(align) { + if !offset.is_aligned(align) { arg.pad_with(Reg::i32()); } } else { arg.extend_integer_width_to(32); } - *offset = offset.abi_align(align) + size.abi_align(align); + *offset = offset.align_to(align) + size.align_to(align); } pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType) diff --git a/src/librustc_target/abi/call/mips64.rs b/src/librustc_target/abi/call/mips64.rs index adf5a3c94ea..d375b163164 100644 --- a/src/librustc_target/abi/call/mips64.rs +++ b/src/librustc_target/abi/call/mips64.rs @@ -118,9 +118,9 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>) // We only care about aligned doubles if let abi::Abi::Scalar(ref scalar) = field.abi { if let abi::Float(abi::FloatTy::F64) = scalar.value { - if offset.is_abi_aligned(dl.f64_align) { + if offset.is_aligned(dl.f64_align.abi) { // Insert enough integers to cover [last_offset, offset) - assert!(last_offset.is_abi_aligned(dl.f64_align)); + assert!(last_offset.is_aligned(dl.f64_align.abi)); for _ in 0..((offset - last_offset).bits() / 64) .min((prefix.len() - prefix_index) as u64) { diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index 289a76eae8f..489bb37fc26 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use abi::{self, Abi, AbiAndPrefAlign, FieldPlacement, Size}; +use abi::{self, Abi, Align, FieldPlacement, Size}; use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; use spec::HasTargetSpec; @@ -80,7 +80,7 @@ mod attr_impl { pub struct ArgAttributes { pub regular: ArgAttribute, pub pointee_size: Size, - pub pointee_align: Option + pub pointee_align: Option } impl ArgAttributes { @@ -137,28 +137,28 @@ impl Reg { } impl Reg { - pub fn align(&self, cx: &C) -> AbiAndPrefAlign { + pub fn align(&self, cx: &C) -> Align { let dl = cx.data_layout(); match self.kind { RegKind::Integer => { match self.size.bits() { - 1 => dl.i1_align, - 2..=8 => dl.i8_align, - 9..=16 => dl.i16_align, - 17..=32 => dl.i32_align, - 33..=64 => dl.i64_align, - 65..=128 => dl.i128_align, + 1 => dl.i1_align.abi, + 2..=8 => dl.i8_align.abi, + 9..=16 => dl.i16_align.abi, + 17..=32 => dl.i32_align.abi, + 33..=64 => dl.i64_align.abi, + 65..=128 => dl.i128_align.abi, _ => panic!("unsupported integer: {:?}", self) } } RegKind::Float => { match self.size.bits() { - 32 => dl.f32_align, - 64 => dl.f64_align, + 32 => dl.f32_align.abi, + 64 => dl.f64_align.abi, _ => panic!("unsupported float: {:?}", self) } } - RegKind::Vector => dl.vector_align(self.size) + RegKind::Vector => dl.vector_align(self.size).abi, } } } @@ -188,7 +188,7 @@ impl From for Uniform { } impl Uniform { - pub fn align(&self, cx: &C) -> AbiAndPrefAlign { + pub fn align(&self, cx: &C) -> Align { self.unit.align(cx) } } @@ -227,13 +227,13 @@ impl CastTarget { pub fn size(&self, cx: &C) -> Size { (self.prefix_chunk * self.prefix.iter().filter(|x| x.is_some()).count() as u64) - .abi_align(self.rest.align(cx)) + self.rest.total + .align_to(self.rest.align(cx)) + self.rest.total } - pub fn align(&self, cx: &C) -> AbiAndPrefAlign { + pub fn align(&self, cx: &C) -> Align { self.prefix.iter() .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk }.align(cx))) - .fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)), + .fold(cx.data_layout().aggregate_align.abi.max(self.rest.align(cx)), |acc, align| acc.max(align)) } } @@ -369,7 +369,7 @@ impl<'a, Ty> ArgType<'a, Ty> { attrs.pointee_size = self.layout.size; // FIXME(eddyb) We should be doing this, but at least on // i686-pc-windows-msvc, it results in wrong stack offsets. - // attrs.pointee_align = Some(self.layout.align); + // attrs.pointee_align = Some(self.layout.align.abi); let extra_attrs = if self.layout.is_unsized() { Some(ArgAttributes::new()) diff --git a/src/librustc_target/abi/call/powerpc.rs b/src/librustc_target/abi/call/powerpc.rs index b9b012020b7..a71f3226320 100644 --- a/src/librustc_target/abi/call/powerpc.rs +++ b/src/librustc_target/abi/call/powerpc.rs @@ -27,21 +27,21 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType, offset: &mut Size) { let dl = cx.data_layout(); let size = arg.layout.size; - let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align); + let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align).abi; if arg.layout.is_aggregate() { arg.cast_to(Uniform { unit: Reg::i32(), total: size }); - if !offset.is_abi_aligned(align) { + if !offset.is_aligned(align) { arg.pad_with(Reg::i32()); } } else { arg.extend_integer_width_to(32); } - *offset = offset.abi_align(align) + size.abi_align(align); + *offset = offset.align_to(align) + size.align_to(align); } pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType) diff --git a/src/librustc_target/abi/call/powerpc64.rs b/src/librustc_target/abi/call/powerpc64.rs index 7d78d1d75d5..99f07c5702a 100644 --- a/src/librustc_target/abi/call/powerpc64.rs +++ b/src/librustc_target/abi/call/powerpc64.rs @@ -121,7 +121,7 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>, abi: ABI) // Aggregates larger than a doubleword should be padded // at the tail to fill out a whole number of doublewords. let reg_i64 = Reg::i64(); - (reg_i64, size.abi_align(reg_i64.align(cx))) + (reg_i64, size.align_to(reg_i64.align(cx))) }; arg.cast_to(Uniform { diff --git a/src/librustc_target/abi/call/sparc.rs b/src/librustc_target/abi/call/sparc.rs index a40cb6c76f0..abe0bd07892 100644 --- a/src/librustc_target/abi/call/sparc.rs +++ b/src/librustc_target/abi/call/sparc.rs @@ -27,21 +27,21 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType, offset: &mut Size) { let dl = cx.data_layout(); let size = arg.layout.size; - let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align); + let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align).abi; if arg.layout.is_aggregate() { arg.cast_to(Uniform { unit: Reg::i32(), total: size }); - if !offset.is_abi_aligned(align) { + if !offset.is_aligned(align) { arg.pad_with(Reg::i32()); } } else { arg.extend_integer_width_to(32); } - *offset = offset.abi_align(align) + size.abi_align(align); + *offset = offset.align_to(align) + size.align_to(align); } pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType) diff --git a/src/librustc_target/abi/call/x86_64.rs b/src/librustc_target/abi/call/x86_64.rs index 4c944650893..f091f80924d 100644 --- a/src/librustc_target/abi/call/x86_64.rs +++ b/src/librustc_target/abi/call/x86_64.rs @@ -41,7 +41,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &ArgType<'a, Ty>) where Ty: TyLayoutMethods<'a, C> + Copy, C: LayoutOf> + HasDataLayout { - if !off.is_abi_aligned(layout.align) { + if !off.is_aligned(layout.align.abi) { if !layout.is_zst() { return Err(Memory); } diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 2eabe94754d..50ce0ad6915 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -277,14 +277,14 @@ impl Size { } #[inline] - pub fn abi_align(self, align: AbiAndPrefAlign) -> Size { - let mask = align.abi.bytes() - 1; + pub fn align_to(self, align: Align) -> Size { + let mask = align.bytes() - 1; Size::from_bytes((self.bytes() + mask) & !mask) } #[inline] - pub fn is_abi_aligned(self, align: AbiAndPrefAlign) -> bool { - let mask = align.abi.bytes() - 1; + pub fn is_aligned(self, align: Align) -> bool { + let mask = align.bytes() - 1; self.bytes() & mask == 0 } @@ -425,7 +425,6 @@ impl Align { /// A pair of aligments, ABI-mandated and preferred. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] -#[derive(PartialOrd, Ord)] // FIXME(eddyb) remove (error prone/incorrect) pub struct AbiAndPrefAlign { pub abi: Align, pub pref: Align, @@ -510,10 +509,9 @@ impl Integer { } /// Find the smallest integer with the given alignment. - pub fn for_abi_align(cx: &C, align: AbiAndPrefAlign) -> Option { + pub fn for_align(cx: &C, wanted: Align) -> Option { let dl = cx.data_layout(); - let wanted = align.abi; for &candidate in &[I8, I16, I32, I64, I128] { if wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() { return Some(candidate); @@ -523,10 +521,9 @@ impl Integer { } /// Find the largest integer with the given alignment or less. - pub fn approximate_abi_align(cx: &C, align: AbiAndPrefAlign) -> Integer { + pub fn approximate_align(cx: &C, wanted: Align) -> Integer { let dl = cx.data_layout(); - let wanted = align.abi; // FIXME(eddyb) maybe include I128 in the future, when it works everywhere. for &candidate in &[I64, I32, I16] { if wanted >= candidate.align(dl).abi && wanted.bytes() >= candidate.size().bytes() { From d1cd4e8d0d383842acfe2d6ea75eed1e0c0909ac Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 21 Nov 2018 21:56:23 -0800 Subject: [PATCH 0144/1984] Move a flaky process test out of libstd This test ensures that everything in `env::vars()` is inherited but that's not actually true because other tests may add env vars after we spawn the process, causing the test to be flaky! This commit moves the test to a run-pass test where it can execute in isolation. Along the way this removes a lot of the platform specificity of the test, using iteslf to print the environment instead of a foreign process. --- src/libstd/process.rs | 36 -------------------------------- src/test/run-pass/inherit-env.rs | 25 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 36 deletions(-) create mode 100644 src/test/run-pass/inherit-env.rs diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 51481e129df..2d0848252be 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1889,42 +1889,6 @@ mod tests { cmd } - #[test] - fn test_inherit_env() { - use env; - - let result = env_cmd().output().unwrap(); - let output = String::from_utf8(result.stdout).unwrap(); - - for (ref k, ref v) in env::vars() { - // Don't check android RANDOM variable which seems to change - // whenever the shell runs, and our `env_cmd` is indeed running a - // shell which means it'll get a different RANDOM than we probably - // have. - // - // Also skip env vars with `-` in the name on android because, well, - // I'm not sure. It appears though that the `set` command above does - // not print env vars with `-` in the name, so we just skip them - // here as we won't find them in the output. Note that most env vars - // use `_` instead of `-`, but our build system sets a few env vars - // with `-` in the name. - if cfg!(target_os = "android") && - (*k == "RANDOM" || k.contains("-")) { - continue - } - - // Windows has hidden environment variables whose names start with - // equals signs (`=`). Those do not show up in the output of the - // `set` command. - assert!((cfg!(windows) && k.starts_with("=")) || - k.starts_with("DYLD") || - output.contains(&format!("{}={}", *k, *v)) || - output.contains(&format!("{}='{}'", *k, *v)), - "output doesn't contain `{}={}`\n{}", - k, v, output); - } - } - #[test] fn test_override_env() { use env; diff --git a/src/test/run-pass/inherit-env.rs b/src/test/run-pass/inherit-env.rs new file mode 100644 index 00000000000..856d3a5f72d --- /dev/null +++ b/src/test/run-pass/inherit-env.rs @@ -0,0 +1,25 @@ +// ignore-emscripten +// ignore-wasm32 + +use std::env; +use std::process::Command; + +fn main() { + if env::args().nth(1).map(|s| s == "print").unwrap_or(false) { + for (k, v) in env::vars() { + println!("{}={}", k, v); + } + return + } + + let me = env::current_exe().unwrap(); + let result = Command::new(me).arg("print").output().unwrap(); + let output = String::from_utf8(result.stdout).unwrap(); + + for (k, v) in env::vars() { + assert!(output.contains(&format!("{}={}", k, v)), + "output doesn't contain `{}={}`\n{}", + k, v, output); + } +} + From f41423c75f929bfad12846e64db174621a238d74 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Thu, 22 Nov 2018 00:59:37 -0800 Subject: [PATCH 0145/1984] Pass additional linker flags when targeting Fuchsia This is a follow up to 8aa9267 which changed the driver to use lld directly rather than invoking it through Clang. This change ensures we pass all the necessary flags to lld. --- src/librustc_codegen_llvm/back/link.rs | 10 +++++++++- src/librustc_target/spec/fuchsia_base.rs | 14 ++++++++++---- src/librustc_target/spec/mod.rs | 5 +++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index 20f05d11087..8380b713621 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -19,7 +19,7 @@ use super::rpath::RPathConfig; use super::rpath; use metadata::METADATA_FILENAME; use rustc::session::config::{self, DebugInfo, OutputFilenames, OutputType, PrintRequest}; -use rustc::session::config::{RUST_CGU_EXT, Lto}; +use rustc::session::config::{RUST_CGU_EXT, Lto, Sanitizer}; use rustc::session::filesearch; use rustc::session::search_paths::PathKind; use rustc::session::Session; @@ -491,6 +491,14 @@ fn link_natively(sess: &Session, } cmd.args(&sess.opts.debugging_opts.pre_link_arg); + if sess.target.target.options.is_like_fuchsia { + let prefix = match sess.opts.debugging_opts.sanitizer { + Some(Sanitizer::Address) => "asan/", + _ => "", + }; + cmd.arg(format!("--dynamic-linker={}ld.so.1", prefix)); + } + let pre_link_objects = if crate_type == config::CrateType::Executable { &sess.target.target.options.pre_link_objects_exe } else { diff --git a/src/librustc_target/spec/fuchsia_base.rs b/src/librustc_target/spec/fuchsia_base.rs index 8c20755492e..1d0474e1a9a 100644 --- a/src/librustc_target/spec/fuchsia_base.rs +++ b/src/librustc_target/spec/fuchsia_base.rs @@ -12,9 +12,11 @@ use spec::{LldFlavor, LinkArgs, LinkerFlavor, TargetOptions}; use std::default::Default; pub fn opts() -> TargetOptions { - let mut args = LinkArgs::new(); - args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec![ - "--build-id".to_string(), "--hash-style=gnu".to_string(), + let mut pre_link_args = LinkArgs::new(); + pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec![ + "--build-id".to_string(), + "--eh-frame-hdr".to_string(), + "--hash-style=gnu".to_string(), "-z".to_string(), "rodynamic".to_string(), ]); @@ -24,9 +26,13 @@ pub fn opts() -> TargetOptions { dynamic_linking: true, executables: true, target_family: Some("unix".to_string()), + is_like_fuchsia: true, linker_is_gnu: true, has_rpath: false, - pre_link_args: args, + pre_link_args: pre_link_args, + pre_link_objects_exe: vec![ + "Scrt1.o".to_string() + ], position_independent_executables: true, has_elf_tls: true, .. Default::default() diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index f67152ee90b..3cf843dc18c 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -558,6 +558,8 @@ pub struct TargetOptions { /// Emscripten toolchain. /// Defaults to false. pub is_like_emscripten: bool, + /// Whether the target toolchain is like Fuchsia's. + pub is_like_fuchsia: bool, /// Whether the linker support GNU-like arguments such as -O. Defaults to false. pub linker_is_gnu: bool, /// The MinGW toolchain has a known issue that prevents it from correctly @@ -723,6 +725,7 @@ impl Default for TargetOptions { is_like_android: false, is_like_emscripten: false, is_like_msvc: false, + is_like_fuchsia: false, linker_is_gnu: false, allows_weak_linkage: true, has_rpath: false, @@ -1013,6 +1016,7 @@ impl Target { key!(is_like_msvc, bool); key!(is_like_emscripten, bool); key!(is_like_android, bool); + key!(is_like_fuchsia, bool); key!(linker_is_gnu, bool); key!(allows_weak_linkage, bool); key!(has_rpath, bool); @@ -1222,6 +1226,7 @@ impl ToJson for Target { target_option_val!(is_like_msvc); target_option_val!(is_like_emscripten); target_option_val!(is_like_android); + target_option_val!(is_like_fuchsia); target_option_val!(linker_is_gnu); target_option_val!(allows_weak_linkage); target_option_val!(has_rpath); From 2d46ae7c37a779fe993687e753b7c544bb26dc38 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 22 Nov 2018 10:54:04 +0100 Subject: [PATCH 0146/1984] expand thread::park explanation --- src/libstd/thread/mod.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 8a845efd413..99f8fa390d2 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -806,9 +806,13 @@ const NOTIFIED: usize = 2; /// In other words, each [`Thread`] acts a bit like a spinlock that can be /// locked and unlocked using `park` and `unpark`. /// +/// Notice that it would be a valid (but inefficient) implementation to make both [`park`] and +/// [`unpark`] NOPs that return immediately. Being unblocked does not imply +/// any synchronization with someone that unparked this thread, it could also be spurious. +/// /// The API is typically used by acquiring a handle to the current thread, /// placing that handle in a shared data structure so that other threads can -/// find it, and then `park`ing. When some desired condition is met, another +/// find it, and then `park`ing in a loop. When some desired condition is met, another /// thread calls [`unpark`] on the handle. /// /// The motivation for this design is twofold: @@ -829,6 +833,7 @@ const NOTIFIED: usize = 2; /// .spawn(|| { /// println!("Parking thread"); /// thread::park(); +/// // We *could* get here spuriously, i.e., way before the 10ms below are over! /// println!("Thread unparked"); /// }) /// .unwrap(); From 7c166f54b201dbefe27d4ab61dfdf640ac3a2722 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 22 Aug 2018 05:50:46 +0300 Subject: [PATCH 0147/1984] Move Cargo.{toml,lock} to the repository root directory. --- CONTRIBUTING.md | 7 +-- src/Cargo.lock => Cargo.lock | 0 src/Cargo.toml => Cargo.toml | 60 +++++++++---------- src/bootstrap/bootstrap.py | 2 +- src/bootstrap/dist.rs | 6 +- src/bootstrap/test.rs | 1 + src/bootstrap/tool.rs | 28 +++++++-- .../rustdoc-ui/failed-doctest-output.stdout | 4 +- src/tools/tidy/src/deps.rs | 8 +-- src/tools/tidy/src/extdeps.rs | 4 +- src/tools/tidy/src/lib.rs | 2 +- 11 files changed, 70 insertions(+), 52 deletions(-) rename src/Cargo.lock => Cargo.lock (100%) rename src/Cargo.toml => Cargo.toml (53%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fe6bea9d8dc..e04b1bdfefd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -494,16 +494,11 @@ the version in `Cargo.lock`, so the build can no longer continue. To resolve this, we need to update `Cargo.lock`. Luckily, cargo provides a command to do this easily. -First, go into the `src/` directory since that is where `Cargo.toml` is in -the rust repository. Then run, `cargo update -p rustfmt-nightly` to solve -the problem. - ``` -$ cd src $ cargo update -p rustfmt-nightly ``` -This should change the version listed in `src/Cargo.lock` to the new version you updated +This should change the version listed in `Cargo.lock` to the new version you updated the submodule to. Running `./x.py build` should work now. ## Writing Documentation diff --git a/src/Cargo.lock b/Cargo.lock similarity index 100% rename from src/Cargo.lock rename to Cargo.lock diff --git a/src/Cargo.toml b/Cargo.toml similarity index 53% rename from src/Cargo.toml rename to Cargo.toml index e8c44ea57c2..1e1d7a40967 100644 --- a/src/Cargo.toml +++ b/Cargo.toml @@ -1,31 +1,31 @@ [workspace] members = [ - "bootstrap", - "rustc", - "libstd", - "libtest", - "librustc_codegen_llvm", - "tools/cargotest", - "tools/clippy", - "tools/compiletest", - "tools/error_index_generator", - "tools/linkchecker", - "tools/rustbook", - "tools/unstable-book-gen", - "tools/tidy", - "tools/build-manifest", - "tools/remote-test-client", - "tools/remote-test-server", - "tools/rust-installer", - "tools/cargo", - "tools/rustdoc", - "tools/rls", - "tools/rustfmt", - "tools/miri", - "tools/rustdoc-themes", + "src/bootstrap", + "src/rustc", + "src/libstd", + "src/libtest", + "src/librustc_codegen_llvm", + "src/tools/cargotest", + "src/tools/clippy", + "src/tools/compiletest", + "src/tools/error_index_generator", + "src/tools/linkchecker", + "src/tools/rustbook", + "src/tools/unstable-book-gen", + "src/tools/tidy", + "src/tools/build-manifest", + "src/tools/remote-test-client", + "src/tools/remote-test-server", + "src/tools/rust-installer", + "src/tools/cargo", + "src/tools/rustdoc", + "src/tools/rls", + "src/tools/rustfmt", + "src/tools/miri", + "src/tools/rustdoc-themes", ] exclude = [ - "tools/rls/test_data", + "src/tools/rls/test_data", ] # Curiously, LLVM 7.0 will segfault if compiled with opt-level=3 @@ -50,18 +50,18 @@ debug-assertions = false # so we use a `[patch]` here to override the github repository with our local # vendored copy. [patch."https://github.com/rust-lang/cargo"] -cargo = { path = "tools/cargo" } +cargo = { path = "src/tools/cargo" } [patch.crates-io] # Similar to Cargo above we want the RLS to use a vendored version of `rustfmt` # that we're shipping as well (to ensure that the rustfmt in RLS and the # `rustfmt` executable are the same exact version). -rustfmt-nightly = { path = "tools/rustfmt" } +rustfmt-nightly = { path = "src/tools/rustfmt" } -# See comments in `tools/rustc-workspace-hack/README.md` for what's going on +# See comments in `src/tools/rustc-workspace-hack/README.md` for what's going on # here -rustc-workspace-hack = { path = 'tools/rustc-workspace-hack' } +rustc-workspace-hack = { path = 'src/tools/rustc-workspace-hack' } [patch."https://github.com/rust-lang-nursery/rust-clippy"] -clippy_lints = { path = "tools/clippy/clippy_lints" } -rustc_tools_util = { path = "tools/clippy/rustc_tools_util" } +clippy_lints = { path = "src/tools/clippy/clippy_lints" } +rustc_tools_util = { path = "src/tools/clippy/rustc_tools_util" } diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index cd48e6aa4c4..d143dffb24b 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -801,7 +801,7 @@ def bootstrap(help_triggered): registry = 'https://example.com' [source.vendored-sources] - directory = '{}/src/vendor' + directory = '{}/vendor' """.format(build.rust_root)) else: if os.path.exists('.cargo'): diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 0aab64465fd..cd8d5642b25 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -851,7 +851,7 @@ impl Step for Src { t!(fs::create_dir_all(&dst_src)); let src_files = [ - "src/Cargo.lock", + "Cargo.lock", ]; // This is the reduced set of paths which will become the rust-src component // (essentially libstd and all of its path dependencies) @@ -949,6 +949,8 @@ impl Step for PlainSourceTarball { "configure", "x.py", "config.toml.example", + "Cargo.toml", + "Cargo.lock", ]; let src_dirs = [ "src", @@ -992,7 +994,7 @@ impl Step for PlainSourceTarball { // Vendor all Cargo dependencies let mut cmd = Command::new(&builder.initial_cargo); cmd.arg("vendor") - .current_dir(&plain_dst_src.join("src")); + .current_dir(&plain_dst_src); builder.run(&mut cmd); } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index e55773011df..c50e6a27033 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1934,6 +1934,7 @@ impl Step for Distcheck { .arg("generate-lockfile") .arg("--manifest-path") .arg(&toml) + .env("__CARGO_TEST_ROOT", &dir) .current_dir(&dir), ); } diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index d8e86644ee0..4acc739db57 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -260,8 +260,13 @@ pub fn prepare_tool_cargo( } macro_rules! tool { - ($($name:ident, $path:expr, $tool_name:expr, $mode:expr - $(,llvm_tools = $llvm:expr)* $(,is_external_tool = $external:expr)*;)+) => { + ($( + $name:ident, $path:expr, $tool_name:expr, $mode:expr + $(,llvm_tools = $llvm:expr)* + $(,is_external_tool = $external:expr)* + $(,cargo_test_root = $cargo_test_root:expr)* + ; + )+) => { #[derive(Copy, PartialEq, Eq, Clone)] pub enum Tool { $( @@ -283,6 +288,15 @@ macro_rules! tool { $(Tool::$name => false $(|| $llvm)*,)+ } } + + /// Whether this tool requires may run Cargo for test crates, + /// which currently needs setting the environment variable + /// `__CARGO_TEST_ROOT` to separate it from the workspace. + pub fn needs_cargo_test_root(&self) -> bool { + match self { + $(Tool::$name => false $(|| $cargo_test_root)*,)+ + } + } } impl<'a> Builder<'a> { @@ -358,8 +372,9 @@ tool!( UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::ToolBootstrap; Tidy, "src/tools/tidy", "tidy", Mode::ToolBootstrap; Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::ToolBootstrap; - CargoTest, "src/tools/cargotest", "cargotest", Mode::ToolBootstrap; - Compiletest, "src/tools/compiletest", "compiletest", Mode::ToolBootstrap, llvm_tools = true; + CargoTest, "src/tools/cargotest", "cargotest", Mode::ToolBootstrap, cargo_test_root = true; + Compiletest, "src/tools/compiletest", "compiletest", Mode::ToolBootstrap, + llvm_tools = true, cargo_test_root = true; BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::ToolBootstrap; RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::ToolBootstrap; RustInstaller, "src/tools/rust-installer", "fabricate", Mode::ToolBootstrap, @@ -678,6 +693,11 @@ impl<'a> Builder<'a> { } } + // Set `__CARGO_TEST_ROOT` to the build directory if needed. + if tool.needs_cargo_test_root() { + cmd.env("__CARGO_TEST_ROOT", &self.config.out); + } + add_lib_path(lib_paths, cmd); } diff --git a/src/test/rustdoc-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout index 527f1355a9e..cab7bda6c67 100644 --- a/src/test/rustdoc-ui/failed-doctest-output.stdout +++ b/src/test/rustdoc-ui/failed-doctest-output.stdout @@ -12,7 +12,7 @@ error[E0425]: cannot find value `no` in this scope 3 | no | ^^ not found in this scope -thread '$DIR/failed-doctest-output.rs - OtherStruct (line 27)' panicked at 'couldn't compile the test', librustdoc/test.rs:323:13 +thread '$DIR/failed-doctest-output.rs - OtherStruct (line 27)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:323:13 note: Run with `RUST_BACKTRACE=1` for a backtrace. ---- $DIR/failed-doctest-output.rs - SomeStruct (line 21) stdout ---- @@ -21,7 +21,7 @@ thread '$DIR/failed-doctest-output.rs - SomeStruct (line 21)' panicked at 'test thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1 note: Run with `RUST_BACKTRACE=1` for a backtrace. -', librustdoc/test.rs:358:17 +', src/librustdoc/test.rs:358:17 failures: diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 2dfb9fc68ac..a40ae8894d5 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Check license of third-party deps by inspecting src/vendor +//! Check license of third-party deps by inspecting vendor use std::collections::{BTreeSet, HashSet, HashMap}; use std::fs::File; @@ -203,7 +203,7 @@ impl<'a> From> for Crate<'a> { /// Specifically, this checks that the license is correct. pub fn check(path: &Path, bad: &mut bool) { // Check licences - let path = path.join("vendor"); + let path = path.join("../vendor"); assert!(path.exists(), "vendor directory missing"); let mut saw_dir = false; for dir in t!(path.read_dir()) { @@ -215,7 +215,7 @@ pub fn check(path: &Path, bad: &mut bool) { dir.path() .to_str() .unwrap() - .contains(&format!("src/vendor/{}", exception)) + .contains(&format!("vendor/{}", exception)) }); if is_exception { continue; @@ -304,7 +304,7 @@ fn get_deps(path: &Path, cargo: &Path) -> Resolve { .arg("--format-version") .arg("1") .arg("--manifest-path") - .arg(path.join("Cargo.toml")) + .arg(path.join("../Cargo.toml")) .output() .expect("Unable to run `cargo metadata`") .stdout; diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs index 7f58b440a83..a78d2d4ee4e 100644 --- a/src/tools/tidy/src/extdeps.rs +++ b/src/tools/tidy/src/extdeps.rs @@ -21,8 +21,8 @@ const WHITELISTED_SOURCES: &[&str] = &[ /// check for external package sources pub fn check(path: &Path, bad: &mut bool) { - // Cargo.lock of rust: src/Cargo.lock - let path = path.join("Cargo.lock"); + // Cargo.lock of rust (tidy runs inside src/) + let path = path.join("../Cargo.lock"); // open and read the whole file let mut cargo_lock = String::new(); diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index e235de9c5e1..700103d35d8 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -64,7 +64,6 @@ fn filter_dirs(path: &Path) -> bool { "src/librustc_data_structures/owning_ref", "src/compiler-rt", "src/liblibc", - "src/vendor", "src/rt/hoedown", "src/tools/cargo", "src/tools/clang", @@ -78,6 +77,7 @@ fn filter_dirs(path: &Path) -> bool { "src/target", "src/stdsimd", "target", + "vendor", ]; skip.iter().any(|p| path.ends_with(p)) } From 8e814ae608d5695d2a1c176cf82773e33ad005f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 21 Nov 2018 15:10:05 +0100 Subject: [PATCH 0148/1984] submodules: update clippy from f5d868c9 to 2f6881c6 ```` missed another one in the README run "util/dev update_lints" rust-lang-nursery/rust-clippy => rust-lang/rust-clippy Address 'clippy::single-match' dogfood lint Fix nit Address travis CI lint failure Update trivially_copy_pass_by_ref with Trait stderr output issue#3318 run trivially_copy_pass_by_ref for traits Update trivially_copy_pass_by_ref with Trait examples Fix awkward wording Document how to lint local Clippy changes with locally built Clippy Enable rustup clippy to refer to the correct documentation rustup https://github.com/rust-lang/rust/pull/52591 remove unused allow() attributes, NFC Add regression test Don't emit suggestion when inside of a macro ```` --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index f5d868c9edf..2f6881c6232 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit f5d868c9edfc6c2a9310d564a2f738bec67dfd6b +Subproject commit 2f6881c62325c34115502b8901bf3ef0931b23cd From 37f719e0d38104b6c7d5fb7302e2388d4d4055df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Heine=20n=C3=A9=20Lang?= Date: Thu, 22 Nov 2018 15:26:16 +0100 Subject: [PATCH 0149/1984] std::str Adapt documentation to reality --- src/libcore/str/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index a316093825a..89efa120a6f 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1424,10 +1424,8 @@ fn contains_nonascii(x: usize) -> bool { (x & NONASCII_MASK) != 0 } -/// Walks through `iter` checking that it's a valid UTF-8 sequence, -/// returning `true` in that case, or, if it is invalid, `false` with -/// `iter` reset such that it is pointing at the first byte in the -/// invalid sequence. +/// Walks through `v` checking that it's a valid UTF-8 sequence, +/// returning `Ok(())` in that case, or, if it is invalid, `Err(err)`. #[inline] fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { let mut index = 0; From b83150e6acb2d80a5885d99cf0fca29b2f2fc513 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 22 Nov 2018 06:41:26 -0500 Subject: [PATCH 0150/1984] only reset non-restricted visibilities --- src/librustc/hir/lowering.rs | 33 +++++++++++++++++++++++++++------ src/librustc_lint/builtin.rs | 10 +--------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5b38263f90f..e53deaf8788 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2752,7 +2752,7 @@ impl<'a> LoweringContext<'a> { id: NodeId, name: &mut Name, attrs: &hir::HirVec, - vis: &hir::Visibility, + vis: &mut hir::Visibility, i: &ItemKind, ) -> hir::ItemKind { match *i { @@ -2955,7 +2955,7 @@ impl<'a> LoweringContext<'a> { tree: &UseTree, prefix: &Path, id: NodeId, - vis: &hir::Visibility, + vis: &mut hir::Visibility, name: &mut Name, attrs: &hir::HirVec, ) -> hir::ItemKind { @@ -3086,7 +3086,7 @@ impl<'a> LoweringContext<'a> { hir_id: new_hir_id, } = self.lower_node_id(id); - let vis = vis.clone(); + let mut vis = vis.clone(); let mut name = name.clone(); let mut prefix = prefix.clone(); @@ -3104,7 +3104,7 @@ impl<'a> LoweringContext<'a> { let item = this.lower_use_tree(use_tree, &prefix, new_id, - &vis, + &mut vis, &mut name, attrs); @@ -3139,6 +3139,27 @@ impl<'a> LoweringContext<'a> { }); } + // Subtle and a bit hacky: we lower the privacy level + // of the list stem to "private" most of the time, but + // not for "restricted" paths. The key thing is that + // we don't want it to stay as `pub` (with no caveats) + // because that affects rustdoc and also the lints + // about `pub` items. But we can't *always* make it + // private -- particularly not for restricted paths -- + // because it contains node-ids that would then be + // unused, failing the check that HirIds are "densely + // assigned". + match vis.node { + hir::VisibilityKind::Public | + hir::VisibilityKind::Crate(_) | + hir::VisibilityKind::Inherited => { + *vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited); + } + hir::VisibilityKind::Restricted { .. } => { + // do nothing here, as described in the comment on the match + } + } + let def = self.expect_full_def_from_use(id).next().unwrap_or(Def::Err); let path = P(self.lower_path_extra(def, &prefix, ParamMode::Explicit, None)); hir::ItemKind::Use(path, hir::UseKind::ListStem) @@ -3384,7 +3405,7 @@ impl<'a> LoweringContext<'a> { pub fn lower_item(&mut self, i: &Item) -> Option { let mut name = i.ident.name; - let vis = self.lower_visibility(&i.vis, None); + let mut vis = self.lower_visibility(&i.vis, None); let attrs = self.lower_attrs(&i.attrs); if let ItemKind::MacroDef(ref def) = i.node { if !def.legacy || attr::contains_name(&i.attrs, "macro_export") || @@ -3403,7 +3424,7 @@ impl<'a> LoweringContext<'a> { return None; } - let node = self.lower_item_kind(i.id, &mut name, &attrs, &vis, &i.node); + let node = self.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node); let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 0348ba1f1af..7dd1ca3493e 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1136,15 +1136,7 @@ impl UnreachablePub { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub { fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { - match item.node { - hir::ItemKind::Use(_, hir::UseKind::ListStem) => { - // Hack: ignore these `use foo::{}` remnants which are just a figment - // our IR. - } - _ => { - self.perform_lint(cx, "item", item.id, &item.vis, item.span, true); - } - } + self.perform_lint(cx, "item", item.id, &item.vis, item.span, true); } fn check_foreign_item(&mut self, cx: &LateContext, foreign_item: &hir::ForeignItem) { From 5f2a173f75204e23737eef128edc74f88dba7f39 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 22 Nov 2018 06:48:13 -0500 Subject: [PATCH 0151/1984] explain how this works --- src/librustc/hir/lowering.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e53deaf8788..b3ba2968c9f 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3070,7 +3070,29 @@ impl<'a> LoweringContext<'a> { hir::ItemKind::Use(path, hir::UseKind::Glob) } UseTreeKind::Nested(ref trees) => { - // Nested imports are desugared into simple imports. + // Nested imports are desugared into simple + // imports. So if we start with + // + // ``` + // pub(x) use foo::{a, b}; + // ``` + // + // we will create three items: + // + // ``` + // pub(x) use foo::a; + // pub(x) use foo::b; + // pub(x) use foo::{}; // <-- this is called the `ListStem` + // ``` + // + // The first two are produced by recursively invoking + // `lower_use_tree` (and indeed there may be things + // like `use foo::{a::{b, c}}` and so forth). They + // wind up being directly added to + // `self.items`. However, the structure of this + // function also requires us to return one item, and + // for that we return the `{}` import (called the + // "`ListStem`"). let prefix = Path { segments, From 01fd0012a1f14cd72330be8655b97caabdcf9411 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 6 Nov 2018 19:44:35 -0700 Subject: [PATCH 0152/1984] Include changes from 1.30.1 in release notes --- RELEASES.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index a455186859f..da09af3edfe 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -74,6 +74,14 @@ Cargo [cargo-rename-reference]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml [const-reference]: https://doc.rust-lang.org/reference/items/functions.html#const-functions +Version 1.30.1 (2018-11-08) +=========================== + +- [Fixed overflow ICE in rustdoc][54199] +- [Cap Cargo progress bar width at 60 in MSYS terminals][cargo/6122] + +[54199]: https://github.com/rust-lang/rust/pull/54199 +[cargo/6122]: https://github.com/rust-lang/cargo/pull/6122 Version 1.30.0 (2018-10-25) ========================== From af9b057156f610df3528a502c668cfed99ce8a1a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 22 Nov 2018 13:43:05 +0100 Subject: [PATCH 0153/1984] drop glue takes in mutable references, it should reflect that in its type --- src/libcore/ptr.rs | 14 ++++++++++++-- src/librustc_mir/interpret/terminator.rs | 3 +++ src/librustc_mir/shim.rs | 7 ++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index e9cf11424ca..ba1028f76c1 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -189,12 +189,22 @@ pub use intrinsics::write_bytes; /// i.e., you do not usually have to worry about such issues unless you call `drop_in_place` /// manually. #[stable(feature = "drop_in_place", since = "1.8.0")] +#[inline(always)] +pub unsafe fn drop_in_place(to_drop: *mut T) { + real_drop_in_place(&mut *to_drop) +} + +// The real `drop_in_place` -- the one that gets called implicitly when variables go +// out of scope -- should have a safe reference and not a raw pointer as argument +// type. When we drop a local variable, we access it with a pointer that behaves +// like a safe reference; transmuting that to a raw pointer does not mean we can +// actually access it with raw pointers. #[lang = "drop_in_place"] #[allow(unconditional_recursion)] -pub unsafe fn drop_in_place(to_drop: *mut T) { +unsafe fn real_drop_in_place(to_drop: &mut T) { // Code here does not matter - this is replaced by the // real drop glue by the compiler. - drop_in_place(to_drop); + real_drop_in_place(to_drop) } /// Creates a null raw pointer. diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 6070b31d3e7..44894656797 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -196,6 +196,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // that will take care to make it UB to leave the range, just // like for transmute). caller.value == callee.value, + (layout::Abi::ScalarPair(ref caller1, ref caller2), + layout::Abi::ScalarPair(ref callee1, ref callee2)) => + caller1.value == callee1.value && caller2.value == callee2.value, // Be conservative _ => false } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 93bf1b3e36e..04079319a78 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -226,8 +226,13 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // The first argument (index 0), but add 1 for the return value. let dropee_ptr = Place::Local(Local::new(1+0)); if tcx.sess.opts.debugging_opts.mir_emit_retag { - // We use raw ptr operations, better prepare the alias tracking for that + // Function arguments should be retagged mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement { + source_info, + kind: StatementKind::Retag { fn_entry: true, place: dropee_ptr.clone() }, + }); + // We use raw ptr operations, better prepare the alias tracking for that + mir.basic_blocks_mut()[START_BLOCK].statements.insert(1, Statement { source_info, kind: StatementKind::EscapeToRaw(Operand::Copy(dropee_ptr.clone())), }) From e1ca4f63f4cee0c468325572b86f00badce70ad7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 22 Nov 2018 17:26:44 +0100 Subject: [PATCH 0154/1984] fix codegen-units tests --- .../item-collection/drop_in_place_intrinsic.rs | 5 +++-- .../item-collection/generic-drop-glue.rs | 12 ++++++------ .../instantiation-through-vtable.rs | 4 ++-- .../item-collection/non-generic-drop-glue.rs | 4 ++-- .../item-collection/transitive-drop-glue.rs | 18 +++++++++--------- .../item-collection/tuple-drop-glue.rs | 8 ++++---- .../codegen-units/item-collection/unsizing.rs | 8 ++++---- .../partitioning/extern-drop-glue.rs | 6 +++--- .../partitioning/local-drop-glue.rs | 8 ++++---- .../partitioning/vtable-through-const.rs | 2 +- 10 files changed, 38 insertions(+), 37 deletions(-) diff --git a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs index cec88f1c6a2..1793a311f96 100644 --- a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs +++ b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs @@ -14,7 +14,7 @@ #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ drop_in_place_intrinsic-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ drop_in_place_intrinsic-cgu.0[Internal] struct StructWithDtor(u32); impl Drop for StructWithDtor { @@ -26,7 +26,7 @@ impl Drop for StructWithDtor { #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic-cgu.0[Internal] let x = [StructWithDtor(0), StructWithDtor(1)]; drop_slice_in_place(&x); @@ -41,6 +41,7 @@ fn drop_slice_in_place(x: &[StructWithDtor]) { // not have drop-glue for the unsized [StructWithDtor]. This has to be // generated though when the drop_in_place() intrinsic is used. //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic-cgu.0[Internal] ::std::ptr::drop_in_place(x as *const _ as *mut [StructWithDtor]); } } diff --git a/src/test/codegen-units/item-collection/generic-drop-glue.rs b/src/test/codegen-units/item-collection/generic-drop-glue.rs index 5afa519bc59..4ae5832ec4e 100644 --- a/src/test/codegen-units/item-collection/generic-drop-glue.rs +++ b/src/test/codegen-units/item-collection/generic-drop-glue.rs @@ -47,7 +47,7 @@ enum EnumNoDrop { struct NonGenericNoDrop(i32); struct NonGenericWithDrop(i32); -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ generic_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ generic_drop_glue-cgu.0[Internal] impl Drop for NonGenericWithDrop { //~ MONO_ITEM fn generic_drop_glue::{{impl}}[2]::drop[0] @@ -57,11 +57,11 @@ impl Drop for NonGenericWithDrop { //~ MONO_ITEM fn generic_drop_glue::start[0] #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0] let _ = StructWithDrop { x: 0i8, y: 'a' }.x; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]> let _ = StructWithDrop { x: "&str", y: NonGenericNoDrop(0) }.y; @@ -70,17 +70,17 @@ fn start(_: isize, _: *const *const u8) -> isize { // This is supposed to generate drop-glue because it contains a field that // needs to be dropped. - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] let _ = StructNoDrop { x: NonGenericWithDrop(0), y: 0f64 }.y; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0] let _ = match EnumWithDrop::A::(0) { EnumWithDrop::A(x) => x, EnumWithDrop::B(x) => x as i32 }; - //~MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] + //~MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0] let _ = match EnumWithDrop::B::(1.0) { EnumWithDrop::A(x) => x, diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs index d09d343a845..bfa67b16d0e 100644 --- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs @@ -34,13 +34,13 @@ impl Trait for Struct { fn start(_: isize, _: *const *const u8) -> isize { let s1 = Struct { _a: 0u32 }; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ instantiation_through_vtable-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ instantiation_through_vtable-cgu.0[Internal] //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0] //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0] let _ = &s1 as &Trait; let s1 = Struct { _a: 0u64 }; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ instantiation_through_vtable-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ instantiation_through_vtable-cgu.0[Internal] //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0] //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0] let _ = &s1 as &Trait; diff --git a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs index a939dd56cda..2d72383391d 100644 --- a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs +++ b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs @@ -15,7 +15,7 @@ #![deny(dead_code)] #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ non_generic_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ non_generic_drop_glue-cgu.0[Internal] struct StructWithDrop { x: i32 } @@ -29,7 +29,7 @@ struct StructNoDrop { x: i32 } -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ non_generic_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ non_generic_drop_glue-cgu.0[Internal] enum EnumWithDrop { A(i32) } diff --git a/src/test/codegen-units/item-collection/transitive-drop-glue.rs b/src/test/codegen-units/item-collection/transitive-drop-glue.rs index 7bbc9b6d0fb..d90171726b2 100644 --- a/src/test/codegen-units/item-collection/transitive-drop-glue.rs +++ b/src/test/codegen-units/item-collection/transitive-drop-glue.rs @@ -15,11 +15,11 @@ #![deny(dead_code)] #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] struct Root(Intermediate); -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] struct Intermediate(Leaf); -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] struct Leaf; impl Drop for Leaf { @@ -40,15 +40,15 @@ impl Drop for LeafGen { fn start(_: isize, _: *const *const u8) -> isize { let _ = Root(Intermediate(Leaf)); - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0] let _ = RootGen(IntermediateGen(LeafGen(0u32))); - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0] let _ = RootGen(IntermediateGen(LeafGen(0i16))); diff --git a/src/test/codegen-units/item-collection/tuple-drop-glue.rs b/src/test/codegen-units/item-collection/tuple-drop-glue.rs index 865570ccfa5..e94af0c2989 100644 --- a/src/test/codegen-units/item-collection/tuple-drop-glue.rs +++ b/src/test/codegen-units/item-collection/tuple-drop-glue.rs @@ -15,7 +15,7 @@ #![deny(dead_code)] #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ tuple_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ tuple_drop_glue-cgu.0[Internal] struct Dropped; impl Drop for Dropped { @@ -26,11 +26,11 @@ impl Drop for Dropped { //~ MONO_ITEM fn tuple_drop_glue::start[0] #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue-cgu.0[Internal] let x = (0u32, Dropped); - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue-cgu.0[Internal] let x = (0i16, (Dropped, true)); 0 diff --git a/src/test/codegen-units/item-collection/unsizing.rs b/src/test/codegen-units/item-collection/unsizing.rs index 5e9a3258c7a..c85f7fc1bdd 100644 --- a/src/test/codegen-units/item-collection/unsizing.rs +++ b/src/test/codegen-units/item-collection/unsizing.rs @@ -59,13 +59,13 @@ impl, U: ?Sized> CoerceUnsized> for Wrapper fn start(_: isize, _: *const *const u8) -> isize { // simple case let bool_sized = &true; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[0]::foo[0] let _bool_unsized = bool_sized as &Trait; let char_sized = &'a'; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[1]::foo[0] let _char_unsized = char_sized as &Trait; @@ -75,13 +75,13 @@ fn start(_: isize, _: *const *const u8) -> isize { _b: 2, _c: 3.0f64 }; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[2]::foo[0] let _struct_unsized = struct_sized as &Struct; // custom coercion let wrapper_sized = Wrapper(&0u32); - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[3]::foo[0] let _wrapper_sized = wrapper_sized as Wrapper; diff --git a/src/test/codegen-units/partitioning/extern-drop-glue.rs b/src/test/codegen-units/partitioning/extern-drop-glue.rs index cbad3a63884..87b4430b4ca 100644 --- a/src/test/codegen-units/partitioning/extern-drop-glue.rs +++ b/src/test/codegen-units/partitioning/extern-drop-glue.rs @@ -21,14 +21,14 @@ // aux-build:cgu_extern_drop_glue.rs extern crate cgu_extern_drop_glue; -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal] struct LocalStruct(cgu_extern_drop_glue::Struct); //~ MONO_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[External] pub fn user() { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ extern_drop_glue[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ extern_drop_glue[Internal] let _ = LocalStruct(cgu_extern_drop_glue::Struct(0)); } @@ -40,7 +40,7 @@ pub mod mod1 { //~ MONO_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[External] pub fn user() { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ extern_drop_glue-mod1[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ extern_drop_glue-mod1[Internal] let _ = LocalStruct(cgu_extern_drop_glue::Struct(0)); } } diff --git a/src/test/codegen-units/partitioning/local-drop-glue.rs b/src/test/codegen-units/partitioning/local-drop-glue.rs index 98729d99ea9..e09eb318708 100644 --- a/src/test/codegen-units/partitioning/local-drop-glue.rs +++ b/src/test/codegen-units/partitioning/local-drop-glue.rs @@ -17,7 +17,7 @@ #![allow(dead_code)] #![crate_type="rlib"] -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal] struct Struct { _a: u32 } @@ -27,7 +27,7 @@ impl Drop for Struct { fn drop(&mut self) {} } -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ local_drop_glue[Internal] +//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ local_drop_glue[Internal] struct Outer { _a: Struct } @@ -46,10 +46,10 @@ pub mod mod1 { use super::Struct; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ local_drop_glue-mod1[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ local_drop_glue-mod1[Internal] struct Struct2 { _a: Struct, - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal] _b: (u32, Struct), } diff --git a/src/test/codegen-units/partitioning/vtable-through-const.rs b/src/test/codegen-units/partitioning/vtable-through-const.rs index ebda08a29f6..459c6b6f154 100644 --- a/src/test/codegen-units/partitioning/vtable-through-const.rs +++ b/src/test/codegen-units/partitioning/vtable-through-const.rs @@ -76,7 +76,7 @@ mod mod1 { //~ MONO_ITEM fn vtable_through_const::start[0] #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ vtable_through_const[Internal] + //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0] @@ vtable_through_const[Internal] // Since Trait1::do_something() is instantiated via its default implementation, // it is considered a generic and is instantiated here only because it is From d9de72fcac7cfd90742a8fa8e4f6c0efd664ecde Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 22 Nov 2018 17:38:59 +0100 Subject: [PATCH 0155/1984] miri: restrict fn argument punning to Rust ABI --- src/librustc_mir/interpret/terminator.rs | 33 +++++++++++++++--------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 44894656797..11c44fc943d 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -182,6 +182,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } fn check_argument_compat( + rust_abi: bool, caller: TyLayout<'tcx>, callee: TyLayout<'tcx>, ) -> bool { @@ -189,12 +190,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // No question return true; } + if !rust_abi { + // Don't risk anything + return false; + } // Compare layout match (&caller.abi, &callee.abi) { + // Different valid ranges are okay (once we enforce validity, + // that will take care to make it UB to leave the range, just + // like for transmute). (layout::Abi::Scalar(ref caller), layout::Abi::Scalar(ref callee)) => - // Different valid ranges are okay (once we enforce validity, - // that will take care to make it UB to leave the range, just - // like for transmute). caller.value == callee.value, (layout::Abi::ScalarPair(ref caller1, ref caller2), layout::Abi::ScalarPair(ref callee1, ref callee2)) => @@ -207,22 +212,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> /// Pass a single argument, checking the types for compatibility. fn pass_argument( &mut self, - skip_zst: bool, + rust_abi: bool, caller_arg: &mut impl Iterator>, callee_arg: PlaceTy<'tcx, M::PointerTag>, ) -> EvalResult<'tcx> { - if skip_zst && callee_arg.layout.is_zst() { + if rust_abi && callee_arg.layout.is_zst() { // Nothing to do. trace!("Skipping callee ZST"); return Ok(()); } let caller_arg = caller_arg.next() .ok_or_else(|| EvalErrorKind::FunctionArgCountMismatch)?; - if skip_zst { + if rust_abi { debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out"); } // Now, check - if !Self::check_argument_compat(caller_arg.layout, callee_arg.layout) { + if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) { return err!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty)); } // We allow some transmutes here @@ -322,7 +327,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // Figure out how to pass which arguments. // We have two iterators: Where the arguments come from, // and where they go to. - let skip_zst = match caller_abi { + let rust_abi = match caller_abi { Abi::Rust | Abi::RustCall => true, _ => false }; @@ -347,7 +352,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> }; // Skip ZSTs let mut caller_iter = caller_args.iter() - .filter(|op| !skip_zst || !op.layout.is_zst()) + .filter(|op| !rust_abi || !op.layout.is_zst()) .map(|op| *op); // Now we have to spread them out across the callee's locals, @@ -362,11 +367,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // Must be a tuple for i in 0..dest.layout.fields.count() { let dest = self.place_field(dest, i as u64)?; - self.pass_argument(skip_zst, &mut caller_iter, dest)?; + self.pass_argument(rust_abi, &mut caller_iter, dest)?; } } else { // Normal argument - self.pass_argument(skip_zst, &mut caller_iter, dest)?; + self.pass_argument(rust_abi, &mut caller_iter, dest)?; } } // Now we should have no more caller args @@ -377,7 +382,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // Don't forget to check the return type! if let Some(caller_ret) = dest { let callee_ret = self.eval_place(&mir::Place::Local(mir::RETURN_PLACE))?; - if !Self::check_argument_compat(caller_ret.layout, callee_ret.layout) { + if !Self::check_argument_compat( + rust_abi, + caller_ret.layout, + callee_ret.layout, + ) { return err!(FunctionRetMismatch( caller_ret.layout.ty, callee_ret.layout.ty )); From d0f99ddefafb02d66ed7ff13a22e3b7526ba9743 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 22 Nov 2018 09:52:24 -0700 Subject: [PATCH 0156/1984] Fix the tracking issue for hash_raw_entry It used to point to the implementation PR. --- src/libstd/collections/hash/map.rs | 76 +++++++++++++++--------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index d4650bd68d6..7c717d832fa 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1571,7 +1571,7 @@ impl HashMap /// so that the map now contains keys which compare equal, search may start /// acting erratically, with two keys randomly masking each other. Implementations /// are free to assume this doesn't happen (within the limits of memory-safety). - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut { self.reserve(1); RawEntryBuilderMut { map: self } @@ -1592,7 +1592,7 @@ impl HashMap /// `get` should be preferred. /// /// Immutable raw entries have very limited use; you might instead want `raw_entry_mut`. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn raw_entry(&self) -> RawEntryBuilder { RawEntryBuilder { map: self } } @@ -1844,7 +1844,7 @@ impl<'a, K, V> InternalEntry> { /// /// [`HashMap::raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> { map: &'a mut HashMap, } @@ -1858,7 +1858,7 @@ pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> { /// [`HashMap`]: struct.HashMap.html /// [`Entry`]: enum.Entry.html /// [`raw_entry`]: struct.HashMap.html#method.raw_entry -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> { /// An occupied entry. Occupied(RawOccupiedEntryMut<'a, K, V>), @@ -1870,7 +1870,7 @@ pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> { /// It is part of the [`RawEntryMut`] enum. /// /// [`RawEntryMut`]: enum.RawEntryMut.html -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> { elem: FullBucket>, } @@ -1879,7 +1879,7 @@ pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> { /// It is part of the [`RawEntryMut`] enum. /// /// [`RawEntryMut`]: enum.RawEntryMut.html -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawVacantEntryMut<'a, K: 'a, V: 'a, S: 'a> { elem: VacantEntryState>, hash_builder: &'a S, @@ -1890,7 +1890,7 @@ pub struct RawVacantEntryMut<'a, K: 'a, V: 'a, S: 'a> { /// See the [`HashMap::raw_entry`] docs for usage examples. /// /// [`HashMap::raw_entry`]: struct.HashMap.html#method.raw_entry -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawEntryBuilder<'a, K: 'a, V: 'a, S: 'a> { map: &'a HashMap, } @@ -1900,7 +1900,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> K: Eq + Hash, { /// Create a `RawEntryMut` from the given key. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_key(self, k: &Q) -> RawEntryMut<'a, K, V, S> where K: Borrow, Q: Hash + Eq @@ -1911,7 +1911,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> } /// Create a `RawEntryMut` from the given key and its hash. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S> where K: Borrow, Q: Eq @@ -1941,7 +1941,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> } } /// Create a `RawEntryMut` from the given hash. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_hash(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S> where for<'b> F: FnMut(&'b K) -> bool, { @@ -1951,7 +1951,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> /// Search possible locations for an element with hash `hash` until `is_match` returns true for /// one of them. There is no guarantee that all keys passed to `is_match` will have the provided /// hash. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn search_bucket(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S> where for<'b> F: FnMut(&'b K) -> bool, { @@ -1963,7 +1963,7 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> where S: BuildHasher, { /// Access an entry by key. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_key(self, k: &Q) -> Option<(&'a K, &'a V)> where K: Borrow, Q: Hash + Eq @@ -1974,7 +1974,7 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> } /// Access an entry by a key and its hash. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)> where K: Borrow, Q: Hash + Eq @@ -1997,7 +1997,7 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> } /// Access an entry by hash. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_hash(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)> where F: FnMut(&K) -> bool { @@ -2007,7 +2007,7 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> /// Search possible locations for an element with hash `hash` until `is_match` returns true for /// one of them. There is no guarantee that all keys passed to `is_match` will have the provided /// hash. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn search_bucket(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)> where F: FnMut(&K) -> bool { @@ -2033,7 +2033,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 *= 2; /// assert_eq!(map["poneyland"], 6); /// ``` - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V) where K: Hash, S: BuildHasher, @@ -2061,7 +2061,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// /// assert_eq!(map["poneyland"], "hoho".to_string()); /// ``` - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn or_insert_with(self, default: F) -> (&'a mut K, &'a mut V) where F: FnOnce() -> (K, V), K: Hash, @@ -2099,7 +2099,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// .or_insert("poneyland", 0); /// assert_eq!(map["poneyland"], 43); /// ``` - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn and_modify(self, f: F) -> Self where F: FnOnce(&mut K, &mut V) { @@ -2118,82 +2118,82 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> { /// Gets a reference to the key in the entry. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn key(&self) -> &K { self.elem.read().0 } /// Gets a mutable reference to the key in the entry. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn key_mut(&mut self) -> &mut K { self.elem.read_mut().0 } /// Converts the entry into a mutable reference to the key in the entry /// with a lifetime bound to the map itself. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn into_key(self) -> &'a mut K { self.elem.into_mut_refs().0 } /// Gets a reference to the value in the entry. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get(&self) -> &V { self.elem.read().1 } /// Converts the OccupiedEntry into a mutable reference to the value in the entry /// with a lifetime bound to the map itself. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn into_mut(self) -> &'a mut V { self.elem.into_mut_refs().1 } /// Gets a mutable reference to the value in the entry. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get_mut(&mut self) -> &mut V { self.elem.read_mut().1 } /// Gets a reference to the key and value in the entry. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get_key_value(&mut self) -> (&K, &V) { self.elem.read() } /// Gets a mutable reference to the key and value in the entry. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) { self.elem.read_mut() } /// Converts the OccupiedEntry into a mutable reference to the key and value in the entry /// with a lifetime bound to the map itself. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn into_key_value(self) -> (&'a mut K, &'a mut V) { self.elem.into_mut_refs() } /// Sets the value of the entry, and returns the entry's old value. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn insert(&mut self, value: V) -> V { mem::replace(self.get_mut(), value) } /// Sets the value of the entry, and returns the entry's old value. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn insert_key(&mut self, key: K) -> K { mem::replace(self.key_mut(), key) } /// Takes the value out of the entry, and returns it. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn remove(self) -> V { pop_internal(self.elem).1 } /// Take the ownership of the key and value from the map. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn remove_entry(self) -> (K, V) { let (k, v, _) = pop_internal(self.elem); (k, v) @@ -2203,7 +2203,7 @@ impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> { impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V) where K: Hash, S: BuildHasher, @@ -2215,7 +2215,7 @@ impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it. - #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) { let hash = SafeHash::new(hash); let b = match self.elem { @@ -2236,7 +2236,7 @@ impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { } } -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] impl<'a, K, V, S> Debug for RawEntryBuilderMut<'a, K, V, S> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RawEntryBuilder") @@ -2244,7 +2244,7 @@ impl<'a, K, V, S> Debug for RawEntryBuilderMut<'a, K, V, S> { } } -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] impl<'a, K: Debug, V: Debug, S> Debug for RawEntryMut<'a, K, V, S> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -2262,7 +2262,7 @@ impl<'a, K: Debug, V: Debug, S> Debug for RawEntryMut<'a, K, V, S> { } } -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] impl<'a, K: Debug, V: Debug> Debug for RawOccupiedEntryMut<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RawOccupiedEntryMut") @@ -2272,7 +2272,7 @@ impl<'a, K: Debug, V: Debug> Debug for RawOccupiedEntryMut<'a, K, V> { } } -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] impl<'a, K, V, S> Debug for RawVacantEntryMut<'a, K, V, S> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RawVacantEntryMut") @@ -2280,7 +2280,7 @@ impl<'a, K, V, S> Debug for RawVacantEntryMut<'a, K, V, S> { } } -#[unstable(feature = "hash_raw_entry", issue = "54043")] +#[unstable(feature = "hash_raw_entry", issue = "56167")] impl<'a, K, V, S> Debug for RawEntryBuilder<'a, K, V, S> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RawEntryBuilder") From b319715456c08097f2cd936da309ed6e8aec2843 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 22 Nov 2018 12:56:15 -0500 Subject: [PATCH 0157/1984] Disable the self-profiler unless the `-Z self-profile` flag is set Related to #51648 --- src/librustc/session/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index d688d93b808..1187c53305d 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -826,8 +826,10 @@ impl Session { } pub fn profiler ()>(&self, f: F) { - let mut profiler = self.self_profiling.borrow_mut(); - f(&mut profiler); + if self.opts.debugging_opts.self_profile { + let mut profiler = self.self_profiling.borrow_mut(); + f(&mut profiler); + } } pub fn print_profiler_results(&self) { From d6d8a330f86c1a71e9fa3d896718b10662ac3ff8 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 18 Nov 2018 18:06:31 +0100 Subject: [PATCH 0158/1984] Add rustc_codegen_ssa to sysroot --- Cargo.lock | 19 ++++++++++++++++++- src/librustc_codegen_llvm/Cargo.toml | 1 - src/librustc_codegen_ssa/Cargo.toml | 19 +++++++++++++++++++ src/librustc_driver/Cargo.toml | 4 ++++ 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0dd693e7217..44c787e74ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2160,7 +2160,6 @@ dependencies = [ "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_codegen_ssa 0.0.0", "rustc_llvm 0.0.0", ] @@ -2168,10 +2167,27 @@ dependencies = [ name = "rustc_codegen_ssa" version = "0.0.0" dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc 0.0.0", "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_allocator 0.0.0", + "rustc_apfloat 0.0.0", + "rustc_codegen_utils 0.0.0", + "rustc_data_structures 0.0.0", + "rustc_errors 0.0.0", + "rustc_fs_util 0.0.0", + "rustc_incremental 0.0.0", + "rustc_mir 0.0.0", + "rustc_target 0.0.0", + "serialize 0.0.0", + "syntax 0.0.0", + "syntax_pos 0.0.0", ] [[package]] @@ -2230,6 +2246,7 @@ dependencies = [ "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_allocator 0.0.0", "rustc_borrowck 0.0.0", + "rustc_codegen_ssa 0.0.0", "rustc_codegen_utils 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml index 34017009c28..b711502b14b 100644 --- a/src/librustc_codegen_llvm/Cargo.toml +++ b/src/librustc_codegen_llvm/Cargo.toml @@ -13,7 +13,6 @@ test = false cc = "1.0.1" num_cpus = "1.0" rustc-demangle = "0.1.4" -rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } rustc_llvm = { path = "../librustc_llvm" } memmap = "0.6" diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index a158c34f9d1..7b1c7cfb56f 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -6,10 +6,29 @@ version = "0.0.0" [lib] name = "rustc_codegen_ssa" path = "lib.rs" +crate-type = ["dylib"] test = false [dependencies] +bitflags = "1.0.4" cc = "1.0.1" num_cpus = "1.0" rustc-demangle = "0.1.4" memmap = "0.6" +log = "0.4.5" +libc = "0.2.43" +jobserver = "0.1.11" + +serialize = { path = "../libserialize" } +syntax = { path = "../libsyntax" } +syntax_pos = { path = "../libsyntax_pos" } +rustc = { path = "../librustc" } +rustc_allocator = { path = "../librustc_allocator" } +rustc_apfloat = { path = "../librustc_apfloat" } +rustc_codegen_utils = { path = "../librustc_codegen_utils" } +rustc_data_structures = { path = "../librustc_data_structures"} +rustc_errors = { path = "../librustc_errors" } +rustc_fs_util = { path = "../librustc_fs_util" } +rustc_incremental = { path = "../librustc_incremental" } +rustc_mir = { path = "../librustc_mir" } +rustc_target = { path = "../librustc_target" } diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 1e32f5ef6f0..d37186b61d3 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -39,6 +39,10 @@ smallvec = { version = "0.6.5", features = ["union"] } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } +# Make sure rustc_codegen_ssa ends up in the sysroot, because this +# crate is intended to be used by codegen backends, which may not be in-tree. +rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } + [dependencies.jemalloc-sys] version = '0.1.8' optional = true From 60e4158188b6f580e8fe44f5a52edd3f06e62a83 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 19 Nov 2018 18:28:44 +0100 Subject: [PATCH 0159/1984] Move fake rustc_codegen_ssa dependency from rustc_driver to rustc-main --- Cargo.lock | 2 +- src/librustc_driver/Cargo.toml | 4 ---- src/rustc/Cargo.toml | 4 ++++ 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44c787e74ad..9f109997ad5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2064,6 +2064,7 @@ dependencies = [ name = "rustc-main" version = "0.0.0" dependencies = [ + "rustc_codegen_ssa 0.0.0", "rustc_driver 0.0.0", "rustc_target 0.0.0", ] @@ -2246,7 +2247,6 @@ dependencies = [ "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_allocator 0.0.0", "rustc_borrowck 0.0.0", - "rustc_codegen_ssa 0.0.0", "rustc_codegen_utils 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index d37186b61d3..1e32f5ef6f0 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -39,10 +39,6 @@ smallvec = { version = "0.6.5", features = ["union"] } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } -# Make sure rustc_codegen_ssa ends up in the sysroot, because this -# crate is intended to be used by codegen backends, which may not be in-tree. -rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } - [dependencies.jemalloc-sys] version = '0.1.8' optional = true diff --git a/src/rustc/Cargo.toml b/src/rustc/Cargo.toml index ec822fddef3..32969d09e85 100644 --- a/src/rustc/Cargo.toml +++ b/src/rustc/Cargo.toml @@ -11,5 +11,9 @@ path = "rustc.rs" rustc_target = { path = "../librustc_target" } rustc_driver = { path = "../librustc_driver" } +# Make sure rustc_codegen_ssa ends up in the sysroot, because this +# crate is intended to be used by codegen backends, which may not be in-tree. +rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } + [features] jemalloc = ['rustc_driver/jemalloc-sys'] From abdcb868ff69a5f6a96dd188ff845a1ec67335f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Nov 2018 17:51:13 -0800 Subject: [PATCH 0160/1984] Point at every unexpected lifetime and type argument in E0107 --- src/librustc_typeck/astconv.rs | 57 ++++++++++++++------------ src/test/ui/error-codes/E0107-b.rs | 8 ++++ src/test/ui/error-codes/E0107-b.stderr | 24 +++++++++++ src/test/ui/error-codes/E0107.rs | 3 +- src/test/ui/error-codes/E0107.stderr | 6 ++- 5 files changed, 69 insertions(+), 29 deletions(-) create mode 100644 src/test/ui/error-codes/E0107-b.rs create mode 100644 src/test/ui/error-codes/E0107-b.stderr diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index d388d756438..277f7d34546 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -338,33 +338,31 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { (required, "") }; - let mut span = span; - let label = if required == permitted && provided > permitted { - let diff = provided - permitted; - if diff == 1 { - // In the case when the user has provided too many arguments, - // we want to point to the first unexpected argument. - let first_superfluous_arg: &GenericArg = &args.args[offset + permitted]; - span = first_superfluous_arg.span(); - } - format!( - "{}unexpected {} argument{}", - if diff != 1 { format!("{} ", diff) } else { String::new() }, - kind, - if diff != 1 { "s" } else { "" }, + let (spans, label) = if required == permitted && provided > permitted { + // In the case when the user has provided too many arguments, + // we want to point to the unexpected arguments. + ( + args.args[offset+permitted .. offset+provided] + .iter() + .map(|arg| arg.span()) + .collect(), + format!( + "unexpected {} argument", + kind, + ), ) } else { - format!( + (vec![span], format!( "expected {}{} {} argument{}", quantifier, bound, kind, if bound != 1 { "s" } else { "" }, - ) + )) }; - tcx.sess.struct_span_err_with_code( - span, + let mut err = tcx.sess.struct_span_err_with_code( + spans.clone(), &format!( "wrong number of {} arguments: expected {}{}, found {}", kind, @@ -373,7 +371,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { provided, ), DiagnosticId::Error("E0107".into()) - ).span_label(span, label).emit(); + ); + for span in spans { + err.span_label(span, label.as_str()); + } + err.emit(); provided > required // `suppress_error` }; @@ -1030,13 +1032,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { for item_def_id in associated_types { let assoc_item = tcx.associated_item(item_def_id); let trait_def_id = assoc_item.container.id(); - struct_span_err!(tcx.sess, span, E0191, "the value of the associated type `{}` \ - (from the trait `{}`) must be specified", - assoc_item.ident, - tcx.item_path_str(trait_def_id)) - .span_label(span, format!("missing associated type `{}` value", - assoc_item.ident)) - .emit(); + let mut err = struct_span_err!( + tcx.sess, + span, + E0191, + "the value of the associated type `{}` (from the trait `{}`) must be specified", + assoc_item.ident, + tcx.item_path_str(trait_def_id), + ); + err.span_label(span, format!("missing associated type `{}` value", assoc_item.ident)); + err.emit(); } // Erase the `dummy_self` (`TRAIT_OBJECT_DUMMY_SELF`) used above. diff --git a/src/test/ui/error-codes/E0107-b.rs b/src/test/ui/error-codes/E0107-b.rs new file mode 100644 index 00000000000..58e7718ba5b --- /dev/null +++ b/src/test/ui/error-codes/E0107-b.rs @@ -0,0 +1,8 @@ +pub trait T { + type A; + type B; + type C; +} + pub struct Foo { i: Box> } + + fn main() {} diff --git a/src/test/ui/error-codes/E0107-b.stderr b/src/test/ui/error-codes/E0107-b.stderr new file mode 100644 index 00000000000..28b957dc91e --- /dev/null +++ b/src/test/ui/error-codes/E0107-b.stderr @@ -0,0 +1,24 @@ +error[E0107]: wrong number of type arguments: expected 2, found 4 + --> $DIR/E0107-b.rs:6:42 + | +LL | pub struct Foo { i: Box> } + | ^^^^^ ^^^^^ unexpected type argument + | | + | unexpected type argument + +error[E0191]: the value of the associated type `A` (from the trait `T`) must be specified + --> $DIR/E0107-b.rs:6:26 + | +LL | pub struct Foo { i: Box> } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing associated type `A` value + +error[E0191]: the value of the associated type `C` (from the trait `T`) must be specified + --> $DIR/E0107-b.rs:6:26 + | +LL | pub struct Foo { i: Box> } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing associated type `C` value + +error: aborting due to 3 previous errors + +Some errors occurred: E0107, E0191. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/error-codes/E0107.rs b/src/test/ui/error-codes/E0107.rs index 815c7fefd2a..87ac9e37853 100644 --- a/src/test/ui/error-codes/E0107.rs +++ b/src/test/ui/error-codes/E0107.rs @@ -26,7 +26,8 @@ struct Baz<'a, 'b, 'c> { //~| unexpected lifetime argument foo2: Foo<'a, 'b, 'c>, //~^ ERROR E0107 - //~| 2 unexpected lifetime arguments + //~| unexpected lifetime argument + //~| unexpected lifetime argument } fn main() {} diff --git a/src/test/ui/error-codes/E0107.stderr b/src/test/ui/error-codes/E0107.stderr index 497fa91bd4f..a07c92cf26a 100644 --- a/src/test/ui/error-codes/E0107.stderr +++ b/src/test/ui/error-codes/E0107.stderr @@ -11,10 +11,12 @@ LL | bar: Bar<'a>, | ^^ unexpected lifetime argument error[E0107]: wrong number of lifetime arguments: expected 1, found 3 - --> $DIR/E0107.rs:27:11 + --> $DIR/E0107.rs:27:19 | LL | foo2: Foo<'a, 'b, 'c>, - | ^^^^^^^^^^^^^^^ 2 unexpected lifetime arguments + | ^^ ^^ unexpected lifetime argument + | | + | unexpected lifetime argument error: aborting due to 3 previous errors From 286f7ae1dde03478fc0f36b7d1f3dc97cb47b730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Nov 2018 18:11:37 -0800 Subject: [PATCH 0161/1984] Join multiple E0191 errors in the same location under a single diagnostic --- src/librustc_typeck/astconv.rs | 27 ++++++++++++++----- .../associated-types-incomplete-object.rs | 3 +-- .../associated-types-incomplete-object.stderr | 15 +++++------ src/test/ui/error-codes/E0107-b.stderr | 15 +++++------ 4 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 277f7d34546..906b800ee44 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1029,18 +1029,31 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { associated_types.remove(&projection_bound.projection_def_id()); } - for item_def_id in associated_types { - let assoc_item = tcx.associated_item(item_def_id); - let trait_def_id = assoc_item.container.id(); + if !associated_types.is_empty() { + let names = associated_types.iter().map(|item_def_id| { + let assoc_item = tcx.associated_item(*item_def_id); + let trait_def_id = assoc_item.container.id(); + format!( + "`{}` (from the trait `{}`)", + assoc_item.ident, + tcx.item_path_str(trait_def_id), + ) + }).collect::>().join(", "); let mut err = struct_span_err!( tcx.sess, span, E0191, - "the value of the associated type `{}` (from the trait `{}`) must be specified", - assoc_item.ident, - tcx.item_path_str(trait_def_id), + "the value of the associated type{} {} must be specified", + if associated_types.len() == 1 { "" } else { "s" }, + names, ); - err.span_label(span, format!("missing associated type `{}` value", assoc_item.ident)); + for item_def_id in associated_types { + let assoc_item = tcx.associated_item(item_def_id); + err.span_label( + span, + format!("missing associated type `{}` value", assoc_item.ident), + ); + } err.emit(); } diff --git a/src/test/ui/associated-types/associated-types-incomplete-object.rs b/src/test/ui/associated-types/associated-types-incomplete-object.rs index 9f1df14605b..e575fd695b2 100644 --- a/src/test/ui/associated-types/associated-types-incomplete-object.rs +++ b/src/test/ui/associated-types/associated-types-incomplete-object.rs @@ -37,6 +37,5 @@ pub fn main() { //~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified let d = &42isize as &Foo; - //~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified - //~| ERROR the value of the associated type `B` (from the trait `Foo`) must be specified + //~^ ERROR the value of the associated types `A` (from the trait `Foo`), `B` (from the trait } diff --git a/src/test/ui/associated-types/associated-types-incomplete-object.stderr b/src/test/ui/associated-types/associated-types-incomplete-object.stderr index 95b1c631250..5a3c243efd0 100644 --- a/src/test/ui/associated-types/associated-types-incomplete-object.stderr +++ b/src/test/ui/associated-types/associated-types-incomplete-object.stderr @@ -10,18 +10,15 @@ error[E0191]: the value of the associated type `A` (from the trait `Foo`) must b LL | let c = &42isize as &Foo; | ^^^^^^^^^^^ missing associated type `A` value -error[E0191]: the value of the associated type `A` (from the trait `Foo`) must be specified - --> $DIR/associated-types-incomplete-object.rs:39:26 - | -LL | let d = &42isize as &Foo; - | ^^^ missing associated type `A` value - -error[E0191]: the value of the associated type `B` (from the trait `Foo`) must be specified +error[E0191]: the value of the associated types `A` (from the trait `Foo`), `B` (from the trait `Foo`) must be specified --> $DIR/associated-types-incomplete-object.rs:39:26 | LL | let d = &42isize as &Foo; - | ^^^ missing associated type `B` value + | ^^^ + | | + | missing associated type `A` value + | missing associated type `B` value -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0191`. diff --git a/src/test/ui/error-codes/E0107-b.stderr b/src/test/ui/error-codes/E0107-b.stderr index 28b957dc91e..f779ca1e0b1 100644 --- a/src/test/ui/error-codes/E0107-b.stderr +++ b/src/test/ui/error-codes/E0107-b.stderr @@ -6,19 +6,16 @@ LL | pub struct Foo { i: Box> } | | | unexpected type argument -error[E0191]: the value of the associated type `A` (from the trait `T`) must be specified +error[E0191]: the value of the associated types `A` (from the trait `T`), `C` (from the trait `T`) must be specified --> $DIR/E0107-b.rs:6:26 | LL | pub struct Foo { i: Box> } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing associated type `A` value + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | missing associated type `A` value + | missing associated type `C` value -error[E0191]: the value of the associated type `C` (from the trait `T`) must be specified - --> $DIR/E0107-b.rs:6:26 - | -LL | pub struct Foo { i: Box> } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing associated type `C` value - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors occurred: E0107, E0191. For more information about an error, try `rustc --explain E0107`. From b6f4b29c6df3fc78adbda9c915f01f8e354d9ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Nov 2018 18:14:41 -0800 Subject: [PATCH 0162/1984] Point at the associated type's def span --- src/librustc_typeck/astconv.rs | 4 ++++ ...d-type-projection-from-multiple-supertraits.stderr | 3 +++ .../associated-types-incomplete-object.stderr | 11 +++++++++++ src/test/ui/error-codes/E0107-b.stderr | 6 ++++++ src/test/ui/error-codes/E0191.stderr | 3 +++ src/test/ui/error-codes/E0220.stderr | 3 +++ src/test/ui/issues/issue-19482.stderr | 3 +++ src/test/ui/issues/issue-21950.stderr | 5 +++++ src/test/ui/issues/issue-22434.stderr | 3 +++ src/test/ui/issues/issue-22560.stderr | 5 +++++ src/test/ui/issues/issue-23024.stderr | 5 +++++ src/test/ui/issues/issue-28344.stderr | 10 ++++++++++ src/test/ui/traits/trait-alias-object.stderr | 5 +++++ 13 files changed, 66 insertions(+) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 906b800ee44..173f7ababe3 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1053,6 +1053,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { span, format!("missing associated type `{}` value", assoc_item.ident), ); + err.span_label( + tcx.def_span(item_def_id), + format!("`{}` defined here", assoc_item.ident), + ); } err.emit(); } diff --git a/src/test/ui/associated-type/associated-type-projection-from-multiple-supertraits.stderr b/src/test/ui/associated-type/associated-type-projection-from-multiple-supertraits.stderr index 7a10b6d021f..726078f44a7 100644 --- a/src/test/ui/associated-type/associated-type-projection-from-multiple-supertraits.stderr +++ b/src/test/ui/associated-type/associated-type-projection-from-multiple-supertraits.stderr @@ -25,6 +25,9 @@ LL | fn dent_object(c: BoxCar) { error[E0191]: the value of the associated type `Color` (from the trait `Vehicle`) must be specified --> $DIR/associated-type-projection-from-multiple-supertraits.rs:33:26 | +LL | type Color; + | ----------- `Color` defined here +... LL | fn dent_object(c: BoxCar) { | ^^^^^^^^^^^^^^^^^^^ missing associated type `Color` value diff --git a/src/test/ui/associated-types/associated-types-incomplete-object.stderr b/src/test/ui/associated-types/associated-types-incomplete-object.stderr index 5a3c243efd0..933f059ebf4 100644 --- a/src/test/ui/associated-types/associated-types-incomplete-object.stderr +++ b/src/test/ui/associated-types/associated-types-incomplete-object.stderr @@ -1,18 +1,29 @@ error[E0191]: the value of the associated type `B` (from the trait `Foo`) must be specified --> $DIR/associated-types-incomplete-object.rs:33:26 | +LL | type B; + | ------- `B` defined here +... LL | let b = &42isize as &Foo; | ^^^^^^^^^^^^ missing associated type `B` value error[E0191]: the value of the associated type `A` (from the trait `Foo`) must be specified --> $DIR/associated-types-incomplete-object.rs:36:26 | +LL | type A; + | ------- `A` defined here +... LL | let c = &42isize as &Foo; | ^^^^^^^^^^^ missing associated type `A` value error[E0191]: the value of the associated types `A` (from the trait `Foo`), `B` (from the trait `Foo`) must be specified --> $DIR/associated-types-incomplete-object.rs:39:26 | +LL | type A; + | ------- `A` defined here +LL | type B; + | ------- `B` defined here +... LL | let d = &42isize as &Foo; | ^^^ | | diff --git a/src/test/ui/error-codes/E0107-b.stderr b/src/test/ui/error-codes/E0107-b.stderr index f779ca1e0b1..1e8c683aff6 100644 --- a/src/test/ui/error-codes/E0107-b.stderr +++ b/src/test/ui/error-codes/E0107-b.stderr @@ -9,6 +9,12 @@ LL | pub struct Foo { i: Box> } error[E0191]: the value of the associated types `A` (from the trait `T`), `C` (from the trait `T`) must be specified --> $DIR/E0107-b.rs:6:26 | +LL | type A; + | ------- `A` defined here +LL | type B; +LL | type C; + | ------- `C` defined here +LL | } LL | pub struct Foo { i: Box> } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | diff --git a/src/test/ui/error-codes/E0191.stderr b/src/test/ui/error-codes/E0191.stderr index 08b0a845814..a1f7c935c4a 100644 --- a/src/test/ui/error-codes/E0191.stderr +++ b/src/test/ui/error-codes/E0191.stderr @@ -1,6 +1,9 @@ error[E0191]: the value of the associated type `Bar` (from the trait `Trait`) must be specified --> $DIR/E0191.rs:15:12 | +LL | type Bar; + | --------- `Bar` defined here +... LL | type Foo = Trait; //~ ERROR E0191 | ^^^^^ missing associated type `Bar` value diff --git a/src/test/ui/error-codes/E0220.stderr b/src/test/ui/error-codes/E0220.stderr index c8a587f2b53..7ddd912d4f2 100644 --- a/src/test/ui/error-codes/E0220.stderr +++ b/src/test/ui/error-codes/E0220.stderr @@ -7,6 +7,9 @@ LL | type Foo = Trait; //~ ERROR E0220 error[E0191]: the value of the associated type `Bar` (from the trait `Trait`) must be specified --> $DIR/E0220.rs:15:12 | +LL | type Bar; + | --------- `Bar` defined here +... LL | type Foo = Trait; //~ ERROR E0220 | ^^^^^^^^^^^^ missing associated type `Bar` value diff --git a/src/test/ui/issues/issue-19482.stderr b/src/test/ui/issues/issue-19482.stderr index 5e2d427ab72..7e71b0bd232 100644 --- a/src/test/ui/issues/issue-19482.stderr +++ b/src/test/ui/issues/issue-19482.stderr @@ -1,6 +1,9 @@ error[E0191]: the value of the associated type `A` (from the trait `Foo`) must be specified --> $DIR/issue-19482.rs:20:12 | +LL | type A; + | ------- `A` defined here +... LL | fn bar(x: &Foo) {} | ^^^ missing associated type `A` value diff --git a/src/test/ui/issues/issue-21950.stderr b/src/test/ui/issues/issue-21950.stderr index a2f74a29aab..3359225ab6d 100644 --- a/src/test/ui/issues/issue-21950.stderr +++ b/src/test/ui/issues/issue-21950.stderr @@ -11,6 +11,11 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op | LL | &Add; | ^^^ missing associated type `Output` value + | + ::: $SRC_DIR/libcore/ops/arith.rs:LL:COL + | +LL | type Output; + | ------------ `Output` defined here error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-22434.stderr b/src/test/ui/issues/issue-22434.stderr index 914da801ad4..d951d57444d 100644 --- a/src/test/ui/issues/issue-22434.stderr +++ b/src/test/ui/issues/issue-22434.stderr @@ -1,6 +1,9 @@ error[E0191]: the value of the associated type `A` (from the trait `Foo`) must be specified --> $DIR/issue-22434.rs:15:19 | +LL | type A; + | ------- `A` defined here +... LL | type I<'a> = &'a (Foo + 'a); | ^^^^^^^^ missing associated type `A` value diff --git a/src/test/ui/issues/issue-22560.stderr b/src/test/ui/issues/issue-22560.stderr index b5524036fae..8f736aa0345 100644 --- a/src/test/ui/issues/issue-22560.stderr +++ b/src/test/ui/issues/issue-22560.stderr @@ -29,6 +29,11 @@ LL | | //~^ ERROR E0393 LL | | //~| ERROR E0191 LL | | Sub; | |_______________^ missing associated type `Output` value + | + ::: $SRC_DIR/libcore/ops/arith.rs:LL:COL + | +LL | type Output; + | ------------ `Output` defined here error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-23024.stderr b/src/test/ui/issues/issue-23024.stderr index 129d0945303..8a493468dbf 100644 --- a/src/test/ui/issues/issue-23024.stderr +++ b/src/test/ui/issues/issue-23024.stderr @@ -17,6 +17,11 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op | LL | println!("{:?}",(vfnfer[0] as Fn)(3)); | ^^ missing associated type `Output` value + | + ::: $SRC_DIR/libcore/ops/function.rs:LL:COL + | +LL | type Output; + | ------------ `Output` defined here error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-28344.stderr b/src/test/ui/issues/issue-28344.stderr index 7ef2e906422..67588ba46f2 100644 --- a/src/test/ui/issues/issue-28344.stderr +++ b/src/test/ui/issues/issue-28344.stderr @@ -3,6 +3,11 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op | LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); | ^^^^^^^^^^^^^ missing associated type `Output` value + | + ::: $SRC_DIR/libcore/ops/bit.rs:LL:COL + | +LL | type Output; + | ------------ `Output` defined here error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope --> $DIR/issue-28344.rs:14:17 @@ -17,6 +22,11 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op | LL | let g = BitXor::bitor; | ^^^^^^^^^^^^^ missing associated type `Output` value + | + ::: $SRC_DIR/libcore/ops/bit.rs:LL:COL + | +LL | type Output; + | ------------ `Output` defined here error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope --> $DIR/issue-28344.rs:18:13 diff --git a/src/test/ui/traits/trait-alias-object.stderr b/src/test/ui/traits/trait-alias-object.stderr index 6b7b322a53d..0ae9b0b8864 100644 --- a/src/test/ui/traits/trait-alias-object.stderr +++ b/src/test/ui/traits/trait-alias-object.stderr @@ -11,6 +11,11 @@ error[E0191]: the value of the associated type `Item` (from the trait `std::iter | LL | let _: &dyn IteratorAlias = &vec![123].into_iter(); | ^^^^^^^^^^^^^^^^^ missing associated type `Item` value + | + ::: $SRC_DIR/libcore/iter/iterator.rs:LL:COL + | +LL | type Item; + | ---------- `Item` defined here error: aborting due to 2 previous errors From 48fa974211990ec2dd2b8d8c6949d101fb51bb45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Nov 2018 18:54:34 -0800 Subject: [PATCH 0163/1984] Suggest correct syntax when writing type arg instead of assoc type When confusing an associated type with a type argument, suggest the appropriate syntax. Given `Iterator`, suggest `Iterator`. --- src/librustc_typeck/astconv.rs | 114 +++++++++++------- src/librustc_typeck/collect.rs | 11 +- src/librustc_typeck/lib.rs | 2 +- ...se-type-argument-instead-of-assoc-type.rs} | 0 ...ype-argument-instead-of-assoc-type.stderr} | 8 +- 5 files changed, 88 insertions(+), 47 deletions(-) rename src/test/ui/{error-codes/E0107-b.rs => suggestions/use-type-argument-instead-of-assoc-type.rs} (100%) rename src/test/ui/{error-codes/E0107-b.stderr => suggestions/use-type-argument-instead-of-assoc-type.stderr} (75%) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 173f7ababe3..f1192cf98ae 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -182,7 +182,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { item_segment: &hir::PathSegment) -> &'tcx Substs<'tcx> { - let (substs, assoc_bindings) = item_segment.with_generic_args(|generic_args| { + let (substs, assoc_bindings, _) = item_segment.with_generic_args(|generic_args| { self.create_substs_for_ast_path( span, def_id, @@ -256,7 +256,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { }, def.parent.is_none() && def.has_self, // `has_self` seg.infer_types || suppress_mismatch, // `infer_types` - ) + ).0 } /// Check that the correct number of generic arguments have been provided. @@ -269,7 +269,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { position: GenericArgPosition, has_self: bool, infer_types: bool, - ) -> bool { + ) -> (bool, Option>) { // At this stage we are guaranteed that the generic arguments are in the correct order, e.g. // that lifetimes will proceed types. So it suffices to check the number of each generic // arguments in order to validate them with respect to the generic parameters. @@ -303,13 +303,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { let mut err = tcx.sess.struct_span_err(span, msg); err.span_note(span_late, note); err.emit(); - return true; + return (true, None); } else { let mut multispan = MultiSpan::from_span(span); multispan.push_span_label(span_late, note.to_string()); tcx.lint_node(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, args.args[0].id(), multispan, msg); - return false; + return (false, None); } } } @@ -323,7 +323,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { // For kinds without defaults (i.e. lifetimes), `required == permitted`. // For other kinds (i.e. types), `permitted` may be greater than `required`. if required <= provided && provided <= permitted { - return false; + return (false, None); } // Unfortunately lifetime and type parameter mismatches are typically styled @@ -338,19 +338,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { (required, "") }; + let mut potential_assoc_types: Option> = None; let (spans, label) = if required == permitted && provided > permitted { // In the case when the user has provided too many arguments, // we want to point to the unexpected arguments. - ( - args.args[offset+permitted .. offset+provided] + let spans: Vec = args.args[offset+permitted .. offset+provided] .iter() .map(|arg| arg.span()) - .collect(), - format!( - "unexpected {} argument", - kind, - ), - ) + .collect(); + potential_assoc_types = Some(spans.clone()); + (spans, format!( "unexpected {} argument", kind)) } else { (vec![span], format!( "expected {}{} {} argument{}", @@ -377,7 +374,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } err.emit(); - provided > required // `suppress_error` + (provided > required, // `suppress_error` + potential_assoc_types) }; if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes { @@ -399,7 +397,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { arg_counts.lifetimes, ) } else { - false + (false, None) } } @@ -557,7 +555,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { generic_args: &hir::GenericArgs, infer_types: bool, self_ty: Option>) - -> (&'tcx Substs<'tcx>, Vec>) + -> (&'tcx Substs<'tcx>, Vec>, Option>) { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, @@ -573,7 +571,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { assert_eq!(generic_params.has_self, self_ty.is_some()); let has_self = generic_params.has_self; - Self::check_generic_arg_count( + let (_, potential_assoc_types) = Self::check_generic_arg_count( self.tcx(), span, &generic_params, @@ -678,7 +676,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { debug!("create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}", generic_params, self_ty, substs); - (substs, assoc_bindings) + (substs, assoc_bindings, potential_assoc_types) } /// Instantiates the path for the given trait reference, assuming that it's @@ -720,7 +718,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { self_ty: Ty<'tcx>, poly_projections: &mut Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>, speculative: bool) - -> ty::PolyTraitRef<'tcx> + -> (ty::PolyTraitRef<'tcx>, Option>) { let trait_def_id = self.trait_def_id(trait_ref); @@ -728,11 +726,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1); - let (substs, assoc_bindings) = - self.create_substs_for_ast_trait_ref(trait_ref.path.span, - trait_def_id, - self_ty, - trait_ref.path.segments.last().unwrap()); + let (substs, assoc_bindings, potential_assoc_types) = self.create_substs_for_ast_trait_ref( + trait_ref.path.span, + trait_def_id, + self_ty, + trait_ref.path.segments.last().unwrap(), + ); let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs)); let mut dup_bindings = FxHashMap::default(); @@ -747,14 +746,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { debug!("instantiate_poly_trait_ref({:?}, projections={:?}) -> {:?}", trait_ref, poly_projections, poly_trait_ref); - poly_trait_ref + (poly_trait_ref, potential_assoc_types) } pub fn instantiate_poly_trait_ref(&self, poly_trait_ref: &hir::PolyTraitRef, self_ty: Ty<'tcx>, poly_projections: &mut Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>) - -> ty::PolyTraitRef<'tcx> + -> (ty::PolyTraitRef<'tcx>, Option>) { self.instantiate_poly_trait_ref_inner(&poly_trait_ref.trait_ref, self_ty, poly_projections, false) @@ -767,7 +766,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { trait_segment: &hir::PathSegment) -> ty::TraitRef<'tcx> { - let (substs, assoc_bindings) = + let (substs, assoc_bindings, _) = self.create_substs_for_ast_trait_ref(span, trait_def_id, self_ty, @@ -776,13 +775,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { ty::TraitRef::new(trait_def_id, substs) } - fn create_substs_for_ast_trait_ref(&self, - span: Span, - trait_def_id: DefId, - self_ty: Ty<'tcx>, - trait_segment: &hir::PathSegment) - -> (&'tcx Substs<'tcx>, Vec>) - { + fn create_substs_for_ast_trait_ref( + &self, + span: Span, + trait_def_id: DefId, + self_ty: Ty<'tcx>, + trait_segment: &hir::PathSegment, + ) -> (&'tcx Substs<'tcx>, Vec>, Option>) { debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment); @@ -972,9 +971,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { let mut projection_bounds = Vec::new(); let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF); - let principal = self.instantiate_poly_trait_ref(&trait_bounds[0], - dummy_self, - &mut projection_bounds); + let (principal, potential_assoc_types) = self.instantiate_poly_trait_ref( + &trait_bounds[0], + dummy_self, + &mut projection_bounds, + ); debug!("principal: {:?}", principal); for trait_bound in trait_bounds[1..].iter() { @@ -1047,16 +1048,47 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { if associated_types.len() == 1 { "" } else { "s" }, names, ); - for item_def_id in associated_types { - let assoc_item = tcx.associated_item(item_def_id); + let mut suggest = false; + let mut potential_assoc_types_spans = vec![]; + if let Some(potential_assoc_types) = potential_assoc_types { + if potential_assoc_types.len() == associated_types.len() { + // Only suggest when the amount of missing associated types is equals to the + // extra type arguments present, as that gives us a relatively high confidence + // that the user forgot to give the associtated type's name. The canonical + // example would be trying to use `Iterator` instead of + // `Iterator`. + suggest = true; + potential_assoc_types_spans = potential_assoc_types; + } + } + let mut suggestions = vec![]; + for (i, item_def_id) in associated_types.iter().enumerate() { + let assoc_item = tcx.associated_item(*item_def_id); err.span_label( span, format!("missing associated type `{}` value", assoc_item.ident), ); err.span_label( - tcx.def_span(item_def_id), + tcx.def_span(*item_def_id), format!("`{}` defined here", assoc_item.ident), ); + if suggest { + if let Ok(snippet) = tcx.sess.source_map().span_to_snippet( + potential_assoc_types_spans[i], + ) { + suggestions.push(( + potential_assoc_types_spans[i], + format!("{} = {}", assoc_item.ident, snippet), + )); + } + } + } + if !suggestions.is_empty() { + err.multipart_suggestion_with_applicability( + "if you meant to assign the missing associated type, use the name", + suggestions, + Applicability::MaybeIncorrect, + ); } err.emit(); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index f3c570e8400..a1bb0b53f1f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1892,7 +1892,7 @@ fn explicit_predicates_of<'a, 'tcx>( &hir::GenericBound::Trait(ref poly_trait_ref, _) => { let mut projections = Vec::new(); - let trait_ref = AstConv::instantiate_poly_trait_ref( + let (trait_ref, _) = AstConv::instantiate_poly_trait_ref( &icx, poly_trait_ref, ty, @@ -2016,7 +2016,12 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>( let mut projection_bounds = Vec::new(); let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| { - (astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds), bound.span) + let (poly_trait_ref, _) = astconv.instantiate_poly_trait_ref( + bound, + param_ty, + &mut projection_bounds, + ); + (poly_trait_ref, bound.span) }).collect(); let region_bounds = region_bounds @@ -2057,7 +2062,7 @@ fn predicates_from_bound<'tcx>( match *bound { hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => { let mut projections = Vec::new(); - let pred = astconv.instantiate_poly_trait_ref(tr, param_ty, &mut projections); + let (pred, _) = astconv.instantiate_poly_trait_ref(tr, param_ty, &mut projections); iter::once((pred.to_predicate(), tr.span)).chain( projections .into_iter() diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 1f5998d8ca3..0fba311d7f7 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -389,7 +389,7 @@ pub fn hir_trait_to_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_trait: let env_def_id = tcx.hir.local_def_id(env_node_id); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id); let mut projections = Vec::new(); - let principal = astconv::AstConv::instantiate_poly_trait_ref_inner( + let (principal, _) = astconv::AstConv::instantiate_poly_trait_ref_inner( &item_cx, hir_trait, tcx.types.err, &mut projections, true ); diff --git a/src/test/ui/error-codes/E0107-b.rs b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs similarity index 100% rename from src/test/ui/error-codes/E0107-b.rs rename to src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs diff --git a/src/test/ui/error-codes/E0107-b.stderr b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr similarity index 75% rename from src/test/ui/error-codes/E0107-b.stderr rename to src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr index 1e8c683aff6..053f7010421 100644 --- a/src/test/ui/error-codes/E0107-b.stderr +++ b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr @@ -1,5 +1,5 @@ error[E0107]: wrong number of type arguments: expected 2, found 4 - --> $DIR/E0107-b.rs:6:42 + --> $DIR/use-type-argument-instead-of-assoc-type.rs:6:42 | LL | pub struct Foo { i: Box> } | ^^^^^ ^^^^^ unexpected type argument @@ -7,7 +7,7 @@ LL | pub struct Foo { i: Box> } | unexpected type argument error[E0191]: the value of the associated types `A` (from the trait `T`), `C` (from the trait `T`) must be specified - --> $DIR/E0107-b.rs:6:26 + --> $DIR/use-type-argument-instead-of-assoc-type.rs:6:26 | LL | type A; | ------- `A` defined here @@ -20,6 +20,10 @@ LL | pub struct Foo { i: Box> } | | | missing associated type `A` value | missing associated type `C` value +help: if you meant to assign the missing associated type, use the name + | +LL | pub struct Foo { i: Box> } + | ^^^^^^^^^ ^^^^^^^^^ error: aborting due to 2 previous errors From a5d35631febf78027e5dd7f741bb9f07897d4eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Nov 2018 21:43:08 -0800 Subject: [PATCH 0164/1984] Reword and fix test --- src/librustc_typeck/astconv.rs | 9 +++++++-- src/test/compile-fail/issue-23595-1.rs | 4 +--- ...ated-type-projection-from-multiple-supertraits.stderr | 2 +- .../associated-types-incomplete-object.stderr | 8 ++++---- src/test/ui/error-codes/E0191.stderr | 2 +- src/test/ui/error-codes/E0220.stderr | 2 +- src/test/ui/issues/issue-19482.stderr | 2 +- src/test/ui/issues/issue-21950.stderr | 2 +- src/test/ui/issues/issue-22434.stderr | 2 +- src/test/ui/issues/issue-22560.stderr | 2 +- src/test/ui/issues/issue-23024.stderr | 2 +- src/test/ui/issues/issue-28344.stderr | 4 ++-- .../use-type-argument-instead-of-assoc-type.stderr | 6 +++--- src/test/ui/traits/trait-alias-object.stderr | 2 +- 14 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index f1192cf98ae..b583c0554e8 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1066,7 +1066,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { let assoc_item = tcx.associated_item(*item_def_id); err.span_label( span, - format!("missing associated type `{}` value", assoc_item.ident), + format!("associated type `{}` must be specified", assoc_item.ident), ); err.span_label( tcx.def_span(*item_def_id), @@ -1084,8 +1084,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } } if !suggestions.is_empty() { + let msg = if suggestions.len() == 1 { + "if you meant to specify the associated type, write" + } else { + "if you meant to specify the associated types, write" + }; err.multipart_suggestion_with_applicability( - "if you meant to assign the missing associated type, use the name", + msg, suggestions, Applicability::MaybeIncorrect, ); diff --git a/src/test/compile-fail/issue-23595-1.rs b/src/test/compile-fail/issue-23595-1.rs index a3422d859c6..1e615c4c0db 100644 --- a/src/test/compile-fail/issue-23595-1.rs +++ b/src/test/compile-fail/issue-23595-1.rs @@ -16,9 +16,7 @@ trait Hierarchy { type Value; type ChildKey; type Children = Index; - //~^ ERROR: the value of the associated type `ChildKey` - //~^^ ERROR: the value of the associated type `Children` - //~^^^ ERROR: the value of the associated type `Value` + //~^ ERROR: the value of the associated types `Value` (from the trait `Hierarchy`), `ChildKey` fn data(&self) -> Option<(Self::Value, Self::Children)>; } diff --git a/src/test/ui/associated-type/associated-type-projection-from-multiple-supertraits.stderr b/src/test/ui/associated-type/associated-type-projection-from-multiple-supertraits.stderr index 726078f44a7..b4285c0de29 100644 --- a/src/test/ui/associated-type/associated-type-projection-from-multiple-supertraits.stderr +++ b/src/test/ui/associated-type/associated-type-projection-from-multiple-supertraits.stderr @@ -29,7 +29,7 @@ LL | type Color; | ----------- `Color` defined here ... LL | fn dent_object(c: BoxCar) { - | ^^^^^^^^^^^^^^^^^^^ missing associated type `Color` value + | ^^^^^^^^^^^^^^^^^^^ associated type `Color` must be specified error[E0221]: ambiguous associated type `Color` in bounds of `C` --> $DIR/associated-type-projection-from-multiple-supertraits.rs:38:29 diff --git a/src/test/ui/associated-types/associated-types-incomplete-object.stderr b/src/test/ui/associated-types/associated-types-incomplete-object.stderr index 933f059ebf4..eb8e6f998a5 100644 --- a/src/test/ui/associated-types/associated-types-incomplete-object.stderr +++ b/src/test/ui/associated-types/associated-types-incomplete-object.stderr @@ -5,7 +5,7 @@ LL | type B; | ------- `B` defined here ... LL | let b = &42isize as &Foo; - | ^^^^^^^^^^^^ missing associated type `B` value + | ^^^^^^^^^^^^ associated type `B` must be specified error[E0191]: the value of the associated type `A` (from the trait `Foo`) must be specified --> $DIR/associated-types-incomplete-object.rs:36:26 @@ -14,7 +14,7 @@ LL | type A; | ------- `A` defined here ... LL | let c = &42isize as &Foo; - | ^^^^^^^^^^^ missing associated type `A` value + | ^^^^^^^^^^^ associated type `A` must be specified error[E0191]: the value of the associated types `A` (from the trait `Foo`), `B` (from the trait `Foo`) must be specified --> $DIR/associated-types-incomplete-object.rs:39:26 @@ -27,8 +27,8 @@ LL | type B; LL | let d = &42isize as &Foo; | ^^^ | | - | missing associated type `A` value - | missing associated type `B` value + | associated type `A` must be specified + | associated type `B` must be specified error: aborting due to 3 previous errors diff --git a/src/test/ui/error-codes/E0191.stderr b/src/test/ui/error-codes/E0191.stderr index a1f7c935c4a..f07529e7e9e 100644 --- a/src/test/ui/error-codes/E0191.stderr +++ b/src/test/ui/error-codes/E0191.stderr @@ -5,7 +5,7 @@ LL | type Bar; | --------- `Bar` defined here ... LL | type Foo = Trait; //~ ERROR E0191 - | ^^^^^ missing associated type `Bar` value + | ^^^^^ associated type `Bar` must be specified error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0220.stderr b/src/test/ui/error-codes/E0220.stderr index 7ddd912d4f2..d26e61fba8c 100644 --- a/src/test/ui/error-codes/E0220.stderr +++ b/src/test/ui/error-codes/E0220.stderr @@ -11,7 +11,7 @@ LL | type Bar; | --------- `Bar` defined here ... LL | type Foo = Trait; //~ ERROR E0220 - | ^^^^^^^^^^^^ missing associated type `Bar` value + | ^^^^^^^^^^^^ associated type `Bar` must be specified error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-19482.stderr b/src/test/ui/issues/issue-19482.stderr index 7e71b0bd232..d125438b851 100644 --- a/src/test/ui/issues/issue-19482.stderr +++ b/src/test/ui/issues/issue-19482.stderr @@ -5,7 +5,7 @@ LL | type A; | ------- `A` defined here ... LL | fn bar(x: &Foo) {} - | ^^^ missing associated type `A` value + | ^^^ associated type `A` must be specified error: aborting due to previous error diff --git a/src/test/ui/issues/issue-21950.stderr b/src/test/ui/issues/issue-21950.stderr index 3359225ab6d..2cc064dad1b 100644 --- a/src/test/ui/issues/issue-21950.stderr +++ b/src/test/ui/issues/issue-21950.stderr @@ -10,7 +10,7 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op --> $DIR/issue-21950.rs:17:14 | LL | &Add; - | ^^^ missing associated type `Output` value + | ^^^ associated type `Output` must be specified | ::: $SRC_DIR/libcore/ops/arith.rs:LL:COL | diff --git a/src/test/ui/issues/issue-22434.stderr b/src/test/ui/issues/issue-22434.stderr index d951d57444d..3ba77346a1f 100644 --- a/src/test/ui/issues/issue-22434.stderr +++ b/src/test/ui/issues/issue-22434.stderr @@ -5,7 +5,7 @@ LL | type A; | ------- `A` defined here ... LL | type I<'a> = &'a (Foo + 'a); - | ^^^^^^^^ missing associated type `A` value + | ^^^^^^^^ associated type `A` must be specified error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22560.stderr b/src/test/ui/issues/issue-22560.stderr index 8f736aa0345..bfce870196a 100644 --- a/src/test/ui/issues/issue-22560.stderr +++ b/src/test/ui/issues/issue-22560.stderr @@ -28,7 +28,7 @@ LL | type Test = Add + LL | | //~^ ERROR E0393 LL | | //~| ERROR E0191 LL | | Sub; - | |_______________^ missing associated type `Output` value + | |_______________^ associated type `Output` must be specified | ::: $SRC_DIR/libcore/ops/arith.rs:LL:COL | diff --git a/src/test/ui/issues/issue-23024.stderr b/src/test/ui/issues/issue-23024.stderr index 8a493468dbf..198469ca723 100644 --- a/src/test/ui/issues/issue-23024.stderr +++ b/src/test/ui/issues/issue-23024.stderr @@ -16,7 +16,7 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op --> $DIR/issue-23024.rs:19:35 | LL | println!("{:?}",(vfnfer[0] as Fn)(3)); - | ^^ missing associated type `Output` value + | ^^ associated type `Output` must be specified | ::: $SRC_DIR/libcore/ops/function.rs:LL:COL | diff --git a/src/test/ui/issues/issue-28344.stderr b/src/test/ui/issues/issue-28344.stderr index 67588ba46f2..824ba4b49cb 100644 --- a/src/test/ui/issues/issue-28344.stderr +++ b/src/test/ui/issues/issue-28344.stderr @@ -2,7 +2,7 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op --> $DIR/issue-28344.rs:14:17 | LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); - | ^^^^^^^^^^^^^ missing associated type `Output` value + | ^^^^^^^^^^^^^ associated type `Output` must be specified | ::: $SRC_DIR/libcore/ops/bit.rs:LL:COL | @@ -21,7 +21,7 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op --> $DIR/issue-28344.rs:18:13 | LL | let g = BitXor::bitor; - | ^^^^^^^^^^^^^ missing associated type `Output` value + | ^^^^^^^^^^^^^ associated type `Output` must be specified | ::: $SRC_DIR/libcore/ops/bit.rs:LL:COL | diff --git a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr index 053f7010421..b62b5d3b04c 100644 --- a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr +++ b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr @@ -18,9 +18,9 @@ LL | } LL | pub struct Foo { i: Box> } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | missing associated type `A` value - | missing associated type `C` value -help: if you meant to assign the missing associated type, use the name + | associated type `A` must be specified + | associated type `C` must be specified +help: if you meant to specify the associated types, write | LL | pub struct Foo { i: Box> } | ^^^^^^^^^ ^^^^^^^^^ diff --git a/src/test/ui/traits/trait-alias-object.stderr b/src/test/ui/traits/trait-alias-object.stderr index 0ae9b0b8864..c316c4a6beb 100644 --- a/src/test/ui/traits/trait-alias-object.stderr +++ b/src/test/ui/traits/trait-alias-object.stderr @@ -10,7 +10,7 @@ error[E0191]: the value of the associated type `Item` (from the trait `std::iter --> $DIR/trait-alias-object.rs:18:13 | LL | let _: &dyn IteratorAlias = &vec![123].into_iter(); - | ^^^^^^^^^^^^^^^^^ missing associated type `Item` value + | ^^^^^^^^^^^^^^^^^ associated type `Item` must be specified | ::: $SRC_DIR/libcore/iter/iterator.rs:LL:COL | From 510f836d2378bc9d7ec48e3c39ca83006aadb197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 22 Nov 2018 14:30:33 -0800 Subject: [PATCH 0165/1984] Do not point at associated types from other crates This is a somewhat arbitrary restriction in order to be consistent in the output of the tests regardless of target platform. --- src/librustc_typeck/astconv.rs | 10 ++++++---- src/test/ui/issues/issue-21950.stderr | 5 ----- src/test/ui/issues/issue-22560.stderr | 5 ----- src/test/ui/issues/issue-23024.stderr | 5 ----- src/test/ui/issues/issue-28344.stderr | 10 ---------- src/test/ui/traits/trait-alias-object.stderr | 5 ----- 6 files changed, 6 insertions(+), 34 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index b583c0554e8..a8164c85e82 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1068,10 +1068,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { span, format!("associated type `{}` must be specified", assoc_item.ident), ); - err.span_label( - tcx.def_span(*item_def_id), - format!("`{}` defined here", assoc_item.ident), - ); + if item_def_id.is_local() { + err.span_label( + tcx.def_span(*item_def_id), + format!("`{}` defined here", assoc_item.ident), + ); + } if suggest { if let Ok(snippet) = tcx.sess.source_map().span_to_snippet( potential_assoc_types_spans[i], diff --git a/src/test/ui/issues/issue-21950.stderr b/src/test/ui/issues/issue-21950.stderr index 2cc064dad1b..33c89dd4994 100644 --- a/src/test/ui/issues/issue-21950.stderr +++ b/src/test/ui/issues/issue-21950.stderr @@ -11,11 +11,6 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op | LL | &Add; | ^^^ associated type `Output` must be specified - | - ::: $SRC_DIR/libcore/ops/arith.rs:LL:COL - | -LL | type Output; - | ------------ `Output` defined here error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-22560.stderr b/src/test/ui/issues/issue-22560.stderr index bfce870196a..715f84011f6 100644 --- a/src/test/ui/issues/issue-22560.stderr +++ b/src/test/ui/issues/issue-22560.stderr @@ -29,11 +29,6 @@ LL | | //~^ ERROR E0393 LL | | //~| ERROR E0191 LL | | Sub; | |_______________^ associated type `Output` must be specified - | - ::: $SRC_DIR/libcore/ops/arith.rs:LL:COL - | -LL | type Output; - | ------------ `Output` defined here error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-23024.stderr b/src/test/ui/issues/issue-23024.stderr index 198469ca723..adee12a36d3 100644 --- a/src/test/ui/issues/issue-23024.stderr +++ b/src/test/ui/issues/issue-23024.stderr @@ -17,11 +17,6 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op | LL | println!("{:?}",(vfnfer[0] as Fn)(3)); | ^^ associated type `Output` must be specified - | - ::: $SRC_DIR/libcore/ops/function.rs:LL:COL - | -LL | type Output; - | ------------ `Output` defined here error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-28344.stderr b/src/test/ui/issues/issue-28344.stderr index 824ba4b49cb..734c761d0b7 100644 --- a/src/test/ui/issues/issue-28344.stderr +++ b/src/test/ui/issues/issue-28344.stderr @@ -3,11 +3,6 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op | LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); | ^^^^^^^^^^^^^ associated type `Output` must be specified - | - ::: $SRC_DIR/libcore/ops/bit.rs:LL:COL - | -LL | type Output; - | ------------ `Output` defined here error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope --> $DIR/issue-28344.rs:14:17 @@ -22,11 +17,6 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op | LL | let g = BitXor::bitor; | ^^^^^^^^^^^^^ associated type `Output` must be specified - | - ::: $SRC_DIR/libcore/ops/bit.rs:LL:COL - | -LL | type Output; - | ------------ `Output` defined here error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope --> $DIR/issue-28344.rs:18:13 diff --git a/src/test/ui/traits/trait-alias-object.stderr b/src/test/ui/traits/trait-alias-object.stderr index c316c4a6beb..fdb9427cba7 100644 --- a/src/test/ui/traits/trait-alias-object.stderr +++ b/src/test/ui/traits/trait-alias-object.stderr @@ -11,11 +11,6 @@ error[E0191]: the value of the associated type `Item` (from the trait `std::iter | LL | let _: &dyn IteratorAlias = &vec![123].into_iter(); | ^^^^^^^^^^^^^^^^^ associated type `Item` must be specified - | - ::: $SRC_DIR/libcore/iter/iterator.rs:LL:COL - | -LL | type Item; - | ---------- `Item` defined here error: aborting due to 2 previous errors From 4381772695dfb8ced845fd47e7eada74f9f6bd21 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 22 Nov 2018 22:17:23 +0100 Subject: [PATCH 0166/1984] Fix invalid panic setup message --- src/librustc/session/config.rs | 2 +- src/test/ui/panic-runtime/bad-panic-flag1.rs | 2 +- src/test/ui/panic-runtime/bad-panic-flag1.stderr | 2 +- src/test/ui/panic-runtime/bad-panic-flag2.rs | 2 +- src/test/ui/panic-runtime/bad-panic-flag2.stderr | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 78aabf86e30..07f095fc613 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -802,7 +802,7 @@ macro_rules! options { pub const parse_opt_uint: Option<&'static str> = Some("a number"); pub const parse_panic_strategy: Option<&'static str> = - Some("either `panic` or `abort`"); + Some("either `unwind` or `abort`"); pub const parse_relro_level: Option<&'static str> = Some("one of: `full`, `partial`, or `off`"); pub const parse_sanitizer: Option<&'static str> = diff --git a/src/test/ui/panic-runtime/bad-panic-flag1.rs b/src/test/ui/panic-runtime/bad-panic-flag1.rs index f067b6b8349..4e553c4df2f 100644 --- a/src/test/ui/panic-runtime/bad-panic-flag1.rs +++ b/src/test/ui/panic-runtime/bad-panic-flag1.rs @@ -9,6 +9,6 @@ // except according to those terms. // compile-flags:-C panic=foo -// error-pattern:either `panic` or `abort` was expected +// error-pattern:either `unwind` or `abort` was expected fn main() {} diff --git a/src/test/ui/panic-runtime/bad-panic-flag1.stderr b/src/test/ui/panic-runtime/bad-panic-flag1.stderr index 3a65419c98f..013373c6f93 100644 --- a/src/test/ui/panic-runtime/bad-panic-flag1.stderr +++ b/src/test/ui/panic-runtime/bad-panic-flag1.stderr @@ -1,2 +1,2 @@ -error: incorrect value `foo` for codegen option `panic` - either `panic` or `abort` was expected +error: incorrect value `foo` for codegen option `panic` - either `unwind` or `abort` was expected diff --git a/src/test/ui/panic-runtime/bad-panic-flag2.rs b/src/test/ui/panic-runtime/bad-panic-flag2.rs index 0ecf65f080f..f560e7f4eb2 100644 --- a/src/test/ui/panic-runtime/bad-panic-flag2.rs +++ b/src/test/ui/panic-runtime/bad-panic-flag2.rs @@ -9,6 +9,6 @@ // except according to those terms. // compile-flags:-C panic -// error-pattern:requires either `panic` or `abort` +// error-pattern:requires either `unwind` or `abort` fn main() {} diff --git a/src/test/ui/panic-runtime/bad-panic-flag2.stderr b/src/test/ui/panic-runtime/bad-panic-flag2.stderr index 8d919e55c90..6ab94ea704d 100644 --- a/src/test/ui/panic-runtime/bad-panic-flag2.stderr +++ b/src/test/ui/panic-runtime/bad-panic-flag2.stderr @@ -1,2 +1,2 @@ -error: codegen option `panic` requires either `panic` or `abort` (C panic=) +error: codegen option `panic` requires either `unwind` or `abort` (C panic=) From 7b6ad7a960dd330e8c8401a598bd2f2ec6901100 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 23 Nov 2018 11:04:16 +0100 Subject: [PATCH 0167/1984] make park/unpark example more realistic --- src/libstd/thread/mod.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 99f8fa390d2..4a5ba9b800e 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -827,22 +827,33 @@ const NOTIFIED: usize = 2; /// /// ``` /// use std::thread; +/// use std::sync::{Arc, atomic::{Ordering, AtomicBool}}; /// use std::time::Duration; /// -/// let parked_thread = thread::Builder::new() -/// .spawn(|| { +/// let flag = Arc::new(AtomicBool::new(false)); +/// let flag2 = Arc::clone(&flag); +/// +/// let parked_thread = thread::spawn(move || { +/// // We want to wait until the flag is set. We *could* just spin, but using +/// // park/unpark is more efficient. +/// while !flag2.load(Ordering::Acquire) { /// println!("Parking thread"); /// thread::park(); /// // We *could* get here spuriously, i.e., way before the 10ms below are over! +/// // But that is no problem, we are in a loop until the flag is set anyway. /// println!("Thread unparked"); -/// }) -/// .unwrap(); +/// } +/// println!("Flag received"); +/// }); /// /// // Let some time pass for the thread to be spawned. /// thread::sleep(Duration::from_millis(10)); /// +/// // Set the flag, and let the thread wake up. /// // There is no race condition here, if `unpark` /// // happens first, `park` will return immediately. +/// // Hence there is no risk of a deadlock. +/// flag.store(true, Ordering::Release); /// println!("Unpark the thread"); /// parked_thread.thread().unpark(); /// From 2598a7a56daedbb5a04a234d36fcfbfec447dc26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 23 Nov 2018 12:52:47 +0100 Subject: [PATCH 0168/1984] submodules: update clippy from 2f6881c6 to 754b4c07 Changes: ```` rustup https://github.com/rust-lang/rust/pull/54071/ dependencies: update pulldown-cmark from 0.1 to 0.2 s/file_map/source_map ```` --- Cargo.lock | 12 +++++++++++- src/tools/clippy | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0dd693e7217..6a2b1bc41ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -341,7 +341,7 @@ dependencies = [ "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1641,6 +1641,15 @@ dependencies = [ "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pulldown-cmark" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quick-error" version = "1.2.2" @@ -3373,6 +3382,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" "checksum proptest 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "926d0604475349f463fe44130aae73f2294b5309ab2ca0310b998bd334ef191f" "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" +"checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" diff --git a/src/tools/clippy b/src/tools/clippy index 2f6881c6232..754b4c07233 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 2f6881c62325c34115502b8901bf3ef0931b23cd +Subproject commit 754b4c07233ee18820265bd18467aa82263f9a3a From 44c135b6a908ded2d75105648cd0484350505e4e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 10 Oct 2018 11:48:13 +0200 Subject: [PATCH 0169/1984] use MaybeUninit in core::fmt Code by @japaric, I just split it into individual commits --- src/libcore/fmt/float.rs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index 03e7a9a49d8..d01cd012031 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -9,7 +9,7 @@ // except according to those terms. use fmt::{Formatter, Result, LowerExp, UpperExp, Display, Debug}; -use mem; +use mem::MaybeUninit; use num::flt2dec; // Don't inline this so callers don't use the stack space this function @@ -20,11 +20,11 @@ fn float_to_decimal_common_exact(fmt: &mut Formatter, num: &T, where T: flt2dec::DecodableFloat { unsafe { - let mut buf: [u8; 1024] = mem::uninitialized(); // enough for f32 and f64 - let mut parts: [flt2dec::Part; 4] = mem::uninitialized(); + let mut buf = MaybeUninit::<[u8; 1024]>::uninitialized(); // enough for f32 and f64 + let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninitialized(); let formatted = flt2dec::to_exact_fixed_str(flt2dec::strategy::grisu::format_exact, *num, sign, precision, - false, &mut buf, &mut parts); + false, buf.get_mut(), parts.get_mut()); fmt.pad_formatted_parts(&formatted) } } @@ -38,10 +38,11 @@ fn float_to_decimal_common_shortest(fmt: &mut Formatter, num: &T, { unsafe { // enough for f32 and f64 - let mut buf: [u8; flt2dec::MAX_SIG_DIGITS] = mem::uninitialized(); - let mut parts: [flt2dec::Part; 4] = mem::uninitialized(); + let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninitialized(); + let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninitialized(); let formatted = flt2dec::to_shortest_str(flt2dec::strategy::grisu::format_shortest, *num, - sign, precision, false, &mut buf, &mut parts); + sign, precision, false, buf.get_mut(), + parts.get_mut()); fmt.pad_formatted_parts(&formatted) } } @@ -75,11 +76,11 @@ fn float_to_exponential_common_exact(fmt: &mut Formatter, num: &T, where T: flt2dec::DecodableFloat { unsafe { - let mut buf: [u8; 1024] = mem::uninitialized(); // enough for f32 and f64 - let mut parts: [flt2dec::Part; 6] = mem::uninitialized(); + let mut buf = MaybeUninit::<[u8; 1024]>::uninitialized(); // enough for f32 and f64 + let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninitialized(); let formatted = flt2dec::to_exact_exp_str(flt2dec::strategy::grisu::format_exact, *num, sign, precision, - upper, &mut buf, &mut parts); + upper, buf.get_mut(), parts.get_mut()); fmt.pad_formatted_parts(&formatted) } } @@ -94,11 +95,11 @@ fn float_to_exponential_common_shortest(fmt: &mut Formatter, { unsafe { // enough for f32 and f64 - let mut buf: [u8; flt2dec::MAX_SIG_DIGITS] = mem::uninitialized(); - let mut parts: [flt2dec::Part; 6] = mem::uninitialized(); + let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninitialized(); + let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninitialized(); let formatted = flt2dec::to_shortest_exp_str(flt2dec::strategy::grisu::format_shortest, *num, sign, (0, 0), upper, - &mut buf, &mut parts); + buf.get_mut(), parts.get_mut()); fmt.pad_formatted_parts(&formatted) } } From f950c2cbd522ed7a6da18a1e98b8ce46d80e1133 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 10 Oct 2018 12:02:32 +0200 Subject: [PATCH 0170/1984] use MaybeUninit in core::slice::sort Code by @japaric, I just split it into individual commits --- src/libcore/slice/sort.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs index e4c1fd03f9e..affe84fbef9 100644 --- a/src/libcore/slice/sort.rs +++ b/src/libcore/slice/sort.rs @@ -17,7 +17,7 @@ //! stable sorting implementation. use cmp; -use mem; +use mem::{self, MaybeUninit}; use ptr; /// When dropped, copies from `src` into `dest`. @@ -226,14 +226,14 @@ fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize let mut block_l = BLOCK; let mut start_l = ptr::null_mut(); let mut end_l = ptr::null_mut(); - let mut offsets_l: [u8; BLOCK] = unsafe { mem::uninitialized() }; + let mut offsets_l = MaybeUninit::<[u8; BLOCK]>::uninitialized(); // The current block on the right side (from `r.sub(block_r)` to `r`). let mut r = unsafe { l.add(v.len()) }; let mut block_r = BLOCK; let mut start_r = ptr::null_mut(); let mut end_r = ptr::null_mut(); - let mut offsets_r: [u8; BLOCK] = unsafe { mem::uninitialized() }; + let mut offsets_r = MaybeUninit::<[u8; BLOCK]>::uninitialized(); // FIXME: When we get VLAs, try creating one array of length `min(v.len(), 2 * BLOCK)` rather // than two fixed-size arrays of length `BLOCK`. VLAs might be more cache-efficient. @@ -272,8 +272,8 @@ fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize if start_l == end_l { // Trace `block_l` elements from the left side. - start_l = offsets_l.as_mut_ptr(); - end_l = offsets_l.as_mut_ptr(); + start_l = offsets_l.as_mut_ptr() as *mut u8; + end_l = offsets_l.as_mut_ptr() as *mut u8; let mut elem = l; for i in 0..block_l { @@ -288,8 +288,8 @@ fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize if start_r == end_r { // Trace `block_r` elements from the right side. - start_r = offsets_r.as_mut_ptr(); - end_r = offsets_r.as_mut_ptr(); + start_r = offsets_r.as_mut_ptr() as *mut u8; + end_r = offsets_r.as_mut_ptr() as *mut u8; let mut elem = r; for i in 0..block_r { From 525e8f4368dadd1fe66468ff4c14ee889cf504f7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 10 Oct 2018 12:02:45 +0200 Subject: [PATCH 0171/1984] use MaybeUninit in core::slice::rotate Code by @japaric, I just split it into individual commits --- src/libcore/slice/rotate.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/libcore/slice/rotate.rs b/src/libcore/slice/rotate.rs index 0d182b84974..07153735300 100644 --- a/src/libcore/slice/rotate.rs +++ b/src/libcore/slice/rotate.rs @@ -9,7 +9,7 @@ // except according to those terms. use cmp; -use mem; +use mem::{self, MaybeUninit}; use ptr; /// Rotation is much faster if it has access to a little bit of memory. This @@ -26,12 +26,6 @@ union RawArray { } impl RawArray { - fn new() -> Self { - unsafe { mem::uninitialized() } - } - fn ptr(&self) -> *mut T { - unsafe { &self.typed as *const T as *mut T } - } fn cap() -> usize { if mem::size_of::() == 0 { usize::max_value() @@ -88,8 +82,8 @@ pub unsafe fn ptr_rotate(mut left: usize, mid: *mut T, mut right: usize) { } } - let rawarray = RawArray::new(); - let buf = rawarray.ptr(); + let mut rawarray = MaybeUninit::>::uninitialized(); + let buf = &mut (*rawarray.as_mut_ptr()).typed as *mut [T; 2] as *mut T; let dim = mid.sub(left).add(right); if left <= right { From 0bb2e2d6d49c7c148ec19d72a2e844081de9f623 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 12 Oct 2018 08:59:15 +0200 Subject: [PATCH 0172/1984] use MaybeUninit in core::ptr::{read,read_unaligned} Code by @japaric, I just split it into individual commits --- src/libcore/ptr.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index e9cf11424ca..405f95acf19 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -79,7 +79,7 @@ use ops::{CoerceUnsized, DispatchFromDyn}; use fmt; use hash; use marker::{PhantomData, Unsize}; -use mem; +use mem::{self, MaybeUninit}; use nonzero::NonZero; use cmp::Ordering::{self, Less, Equal, Greater}; @@ -575,9 +575,9 @@ pub unsafe fn replace(dst: *mut T, mut src: T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn read(src: *const T) -> T { - let mut tmp: T = mem::uninitialized(); - copy_nonoverlapping(src, &mut tmp, 1); - tmp + let mut tmp = MaybeUninit::::uninitialized(); + copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); + tmp.into_inner() } /// Reads the value from `src` without moving it. This leaves the @@ -642,11 +642,11 @@ pub unsafe fn read(src: *const T) -> T { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] pub unsafe fn read_unaligned(src: *const T) -> T { - let mut tmp: T = mem::uninitialized(); + let mut tmp = MaybeUninit::::uninitialized(); copy_nonoverlapping(src as *const u8, - &mut tmp as *mut T as *mut u8, + tmp.as_mut_ptr() as *mut u8, mem::size_of::()); - tmp + tmp.into_inner() } /// Overwrites a memory location with the given value without reading or From 3fb03d0650825ba254f67fdd5ac94e83e2622415 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 12 Oct 2018 08:59:38 +0200 Subject: [PATCH 0173/1984] use MaybeUninit in core::ptr::swap Code by @japaric, I just split it into individual commits --- src/libcore/ptr.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 405f95acf19..5032c112f7c 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -295,17 +295,14 @@ pub const fn null_mut() -> *mut T { 0 as *mut T } #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn swap(x: *mut T, y: *mut T) { - // Give ourselves some scratch space to work with - let mut tmp: T = mem::uninitialized(); + // Give ourselves some scratch space to work with. + // We do not have to worry about drops: `MaybeUninit` does nothing when dropped. + let mut tmp = MaybeUninit::::uninitialized(); // Perform the swap - copy_nonoverlapping(x, &mut tmp, 1); + copy_nonoverlapping(x, tmp.as_mut_ptr(), 1); copy(y, x, 1); // `x` and `y` may overlap - copy_nonoverlapping(&tmp, y, 1); - - // y and t now point to the same thing, but we need to completely forget `tmp` - // because it's no longer relevant. - mem::forget(tmp); + copy_nonoverlapping(tmp.get_ref(), y, 1); } /// Swaps `count * size_of::()` bytes between the two regions of memory From 5e27ee76b652dc7fbe5da1d213580c9ada0d65e1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 10 Oct 2018 12:04:07 +0200 Subject: [PATCH 0174/1984] use MaybeUninit in core::ptr::swap_nonoverlapping_bytes Code by @japaric, I just split it into individual commits --- src/libcore/ptr.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 5032c112f7c..947b67e4e9a 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -389,8 +389,8 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { while i + block_size <= len { // Create some uninitialized memory as scratch space // Declaring `t` here avoids aligning the stack when this loop is unused - let mut t: Block = mem::uninitialized(); - let t = &mut t as *mut _ as *mut u8; + let mut t = mem::MaybeUninit::::uninitialized(); + let t = t.as_mut_ptr() as *mut u8; let x = x.add(i); let y = y.add(i); @@ -404,10 +404,10 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { if i < len { // Swap any remaining bytes - let mut t: UnalignedBlock = mem::uninitialized(); + let mut t = mem::MaybeUninit::::uninitialized(); let rem = len - i; - let t = &mut t as *mut _ as *mut u8; + let t = t.as_mut_ptr() as *mut u8; let x = x.add(i); let y = y.add(i); From 59786b020be2fa72829158fb02c58da537b294ee Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 20 Nov 2018 23:37:02 +0100 Subject: [PATCH 0175/1984] use more inlining, and force some of it --- src/libcore/mem.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 56ba10c49f4..a5603ff6a62 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -950,7 +950,7 @@ impl ManuallyDrop { /// ManuallyDrop::new(Box::new(())); /// ``` #[stable(feature = "manually_drop", since = "1.20.0")] - #[inline] + #[inline(always)] pub const fn new(value: T) -> ManuallyDrop { ManuallyDrop { value } } @@ -967,7 +967,7 @@ impl ManuallyDrop { /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`. /// ``` #[stable(feature = "manually_drop", since = "1.20.0")] - #[inline] + #[inline(always)] pub const fn into_inner(slot: ManuallyDrop) -> T { slot.value } @@ -1015,7 +1015,7 @@ impl ManuallyDrop { #[stable(feature = "manually_drop", since = "1.20.0")] impl Deref for ManuallyDrop { type Target = T; - #[inline] + #[inline(always)] fn deref(&self) -> &T { &self.value } @@ -1023,7 +1023,7 @@ impl Deref for ManuallyDrop { #[stable(feature = "manually_drop", since = "1.20.0")] impl DerefMut for ManuallyDrop { - #[inline] + #[inline(always)] fn deref_mut(&mut self) -> &mut T { &mut self.value } @@ -1044,6 +1044,7 @@ impl MaybeUninit { /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. /// It is your responsibility to make sure `T` gets dropped if it got initialized. #[unstable(feature = "maybe_uninit", issue = "53491")] + #[inline(always)] pub const fn new(val: T) -> MaybeUninit { MaybeUninit { value: ManuallyDrop::new(val) } } @@ -1053,6 +1054,7 @@ impl MaybeUninit { /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. /// It is your responsibility to make sure `T` gets dropped if it got initialized. #[unstable(feature = "maybe_uninit", issue = "53491")] + #[inline(always)] pub const fn uninitialized() -> MaybeUninit { MaybeUninit { uninit: () } } @@ -1066,6 +1068,7 @@ impl MaybeUninit { /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. /// It is your responsibility to make sure `T` gets dropped if it got initialized. #[unstable(feature = "maybe_uninit", issue = "53491")] + #[inline] pub fn zeroed() -> MaybeUninit { let mut u = MaybeUninit::::uninitialized(); unsafe { @@ -1076,6 +1079,7 @@ impl MaybeUninit { /// Set the value of the `MaybeUninit`. This overwrites any previous value without dropping it. #[unstable(feature = "maybe_uninit", issue = "53491")] + #[inline(always)] pub fn set(&mut self, val: T) { unsafe { self.value = ManuallyDrop::new(val); @@ -1091,6 +1095,7 @@ impl MaybeUninit { /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized /// state, otherwise this will immediately cause undefined behavior. #[unstable(feature = "maybe_uninit", issue = "53491")] + #[inline(always)] pub unsafe fn into_inner(self) -> T { ManuallyDrop::into_inner(self.value) } @@ -1102,6 +1107,7 @@ impl MaybeUninit { /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized /// state, otherwise this will immediately cause undefined behavior. #[unstable(feature = "maybe_uninit", issue = "53491")] + #[inline(always)] pub unsafe fn get_ref(&self) -> &T { &*self.value } @@ -1113,6 +1119,7 @@ impl MaybeUninit { /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized /// state, otherwise this will immediately cause undefined behavior. #[unstable(feature = "maybe_uninit", issue = "53491")] + #[inline(always)] pub unsafe fn get_mut(&mut self) -> &mut T { &mut *self.value } @@ -1120,6 +1127,7 @@ impl MaybeUninit { /// Get a pointer to the contained value. Reading from this pointer will be undefined /// behavior unless the `MaybeUninit` is initialized. #[unstable(feature = "maybe_uninit", issue = "53491")] + #[inline(always)] pub fn as_ptr(&self) -> *const T { unsafe { &*self.value as *const T } } @@ -1127,6 +1135,7 @@ impl MaybeUninit { /// Get a mutable pointer to the contained value. Reading from this pointer will be undefined /// behavior unless the `MaybeUninit` is initialized. #[unstable(feature = "maybe_uninit", issue = "53491")] + #[inline(always)] pub fn as_mut_ptr(&mut self) -> *mut T { unsafe { &mut *self.value as *mut T } } From ea9ccb6046aa1733aa1761fc942f8432fb63f107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 25 Oct 2018 10:09:19 -0700 Subject: [PATCH 0176/1984] Point at end of macro arm when encountering EOF Fix #52866 --- src/libsyntax/ext/tt/macro_parser.rs | 11 +++++++++-- src/libsyntax/ext/tt/macro_rules.rs | 9 +++++++++ src/test/ui/directory_ownership/macro-expanded-mod.rs | 3 ++- .../ui/directory_ownership/macro-expanded-mod.stderr | 6 +++--- .../edition-keywords-2018-2015-parsing.stderr | 6 +++--- .../edition-keywords-2018-2018-parsing.stderr | 6 +++--- src/test/ui/macros/macro-at-most-once-rep-2018.stderr | 8 ++++---- .../ui/macros/macro-in-expression-context-2.stderr | 2 +- 8 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index f31d80acbfa..26604c46be5 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -724,7 +724,14 @@ pub fn parse( "ambiguity: multiple successful parses".to_string(), ); } else { - return Failure(parser.span, token::Eof); + return Failure( + if parser.span.is_dummy() { + parser.span + } else { + sess.source_map().next_point(parser.span) + }, + token::Eof, + ); } } // Performance hack: eof_items may share matchers via Rc with other things that we want @@ -757,7 +764,7 @@ pub fn parse( ); } // If there are no possible next positions AND we aren't waiting for the black-box parser, - // then their is a syntax error. + // then there is a syntax error. else if bb_items.is_empty() && next_items.is_empty() { return Failure(parser.span, parser.token); } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 6bba891278a..b67c46fe6f4 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -53,6 +53,15 @@ impl<'a> ParserAnyMacro<'a> { let fragment = panictry!(parser.parse_ast_fragment(kind, true).map_err(|mut e| { if e.span.is_dummy() { // Get around lack of span in error (#30128) e.set_span(site_span); + } else if parser.token == token::Eof { // (#52866) + e.set_span(parser.sess.source_map().next_point(parser.span)); + } + if parser.token == token::Eof { + let msg = &e.message[0]; + e.message[0] = ( + msg.0.replace(", found ``", ", found the end of the macro arm"), + msg.1, + ); } e })); diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.rs b/src/test/ui/directory_ownership/macro-expanded-mod.rs index 8e631a64f7a..78356f981fc 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.rs +++ b/src/test/ui/directory_ownership/macro-expanded-mod.rs @@ -12,6 +12,7 @@ macro_rules! mod_decl { ($i:ident) => { mod $i; } + //~^ ERROR Cannot declare a non-inline module inside a block } mod macro_expanded_mod_helper { @@ -19,5 +20,5 @@ mod macro_expanded_mod_helper { } fn main() { - mod_decl!(foo); //~ ERROR Cannot declare a non-inline module inside a block + mod_decl!(foo); } diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.stderr b/src/test/ui/directory_ownership/macro-expanded-mod.stderr index a9efcd883c1..f58e864a755 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.stderr +++ b/src/test/ui/directory_ownership/macro-expanded-mod.stderr @@ -1,8 +1,8 @@ error: Cannot declare a non-inline module inside a block unless it has a path attribute - --> $DIR/macro-expanded-mod.rs:22:15 + --> $DIR/macro-expanded-mod.rs:14:28 | -LL | mod_decl!(foo); //~ ERROR Cannot declare a non-inline module inside a block - | ^^^ +LL | ($i:ident) => { mod $i; } + | ^ error: aborting due to previous error diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr index b6ff60f1492..bf7fc28c758 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -22,11 +22,11 @@ error: no rules expected the token `async` LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` | ^^^^^ no rules expected the token `async` -error: expected one of `move`, `|`, or `||`, found `` - --> <::edition_kw_macro_2015::passes_ident macros>:1:22 +error: expected one of `move`, `|`, or `||`, found the end of the macro arm + --> <::edition_kw_macro_2015::passes_ident macros>:1:25 | LL | ( $ i : ident ) => ( $ i ) - | ^^^ expected one of `move`, `|`, or `||` here + | ^ error: aborting due to 5 previous errors diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr index ffe666a7e64..4ab29ba67a0 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -22,11 +22,11 @@ error: no rules expected the token `async` LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` | ^^^^^ no rules expected the token `async` -error: expected one of `move`, `|`, or `||`, found `` - --> <::edition_kw_macro_2018::passes_ident macros>:1:22 +error: expected one of `move`, `|`, or `||`, found the end of the macro arm + --> <::edition_kw_macro_2018::passes_ident macros>:1:25 | LL | ( $ i : ident ) => ( $ i ) - | ^^^ expected one of `move`, `|`, or `||` here + | ^ error: aborting due to 5 previous errors diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr index 25dd66b81f5..19a9cf3a6f5 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr +++ b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr @@ -41,13 +41,13 @@ LL | barplus!(); //~ERROR unexpected end of macro invocation | ^^^^^^^^^^^ unexpected end of macro invocation error: unexpected end of macro invocation - --> $DIR/macro-at-most-once-rep-2018.rs:41:14 + --> $DIR/macro-at-most-once-rep-2018.rs:41:15 | LL | macro_rules! barplus { | -------------------- when calling this macro ... LL | barplus!(a); //~ERROR unexpected end of macro invocation - | ^ unexpected end of macro invocation + | ^ unexpected end of macro invocation error: no rules expected the token `?` --> $DIR/macro-at-most-once-rep-2018.rs:42:15 @@ -77,13 +77,13 @@ LL | barstar!(); //~ERROR unexpected end of macro invocation | ^^^^^^^^^^^ unexpected end of macro invocation error: unexpected end of macro invocation - --> $DIR/macro-at-most-once-rep-2018.rs:48:14 + --> $DIR/macro-at-most-once-rep-2018.rs:48:15 | LL | macro_rules! barstar { | -------------------- when calling this macro ... LL | barstar!(a); //~ERROR unexpected end of macro invocation - | ^ unexpected end of macro invocation + | ^ unexpected end of macro invocation error: no rules expected the token `?` --> $DIR/macro-at-most-once-rep-2018.rs:49:15 diff --git a/src/test/ui/macros/macro-in-expression-context-2.stderr b/src/test/ui/macros/macro-in-expression-context-2.stderr index 80d5dbd66cc..3a4c9c0cdec 100644 --- a/src/test/ui/macros/macro-in-expression-context-2.stderr +++ b/src/test/ui/macros/macro-in-expression-context-2.stderr @@ -1,4 +1,4 @@ -error: expected expression, found `` +error: expected expression, found the end of the macro arm --> $DIR/macro-in-expression-context-2.rs:5:16 | LL | _ => { empty!() } From 34bd86a3fd69a49177cce88b34e16fbfdf8e0304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 4 Nov 2018 13:50:10 -0800 Subject: [PATCH 0177/1984] Add label when replacing primary DUMMY_SP in macro expansion --- src/libsyntax/ext/tt/macro_rules.rs | 1 + src/test/ui/macros/macro-in-expression-context-2.stderr | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index b67c46fe6f4..04f145ce32f 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -53,6 +53,7 @@ impl<'a> ParserAnyMacro<'a> { let fragment = panictry!(parser.parse_ast_fragment(kind, true).map_err(|mut e| { if e.span.is_dummy() { // Get around lack of span in error (#30128) e.set_span(site_span); + e.span_label(site_span, "in this macro expansion"); } else if parser.token == token::Eof { // (#52866) e.set_span(parser.sess.source_map().next_point(parser.span)); } diff --git a/src/test/ui/macros/macro-in-expression-context-2.stderr b/src/test/ui/macros/macro-in-expression-context-2.stderr index 3a4c9c0cdec..0d4f1e82663 100644 --- a/src/test/ui/macros/macro-in-expression-context-2.stderr +++ b/src/test/ui/macros/macro-in-expression-context-2.stderr @@ -2,7 +2,7 @@ error: expected expression, found the end of the macro arm --> $DIR/macro-in-expression-context-2.rs:5:16 | LL | _ => { empty!() } - | ^^^^^^^^ + | ^^^^^^^^ in this macro expansion error: aborting due to previous error From e5cd1edfa190442f4e3e0f53c0ac28f6cc9d15f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 4 Nov 2018 14:01:38 -0800 Subject: [PATCH 0178/1984] Reword incorrect macro invocation primary label --- src/libsyntax/ext/tt/macro_parser.rs | 13 +++++++---- src/libsyntax/ext/tt/macro_rules.rs | 15 +++++++++---- .../edition-keywords-2015-2015-parsing.stderr | 4 ++-- .../edition-keywords-2015-2018-parsing.stderr | 4 ++-- .../edition-keywords-2018-2015-parsing.stderr | 4 ++-- .../edition-keywords-2018-2018-parsing.stderr | 4 ++-- src/test/ui/empty/empty-comment.stderr | 2 +- src/test/ui/fail-simple.stderr | 2 +- src/test/ui/issues/issue-7970a.stderr | 2 +- src/test/ui/issues/issue-7970b.stderr | 2 +- ...-at-most-once-rep-2018-feature-gate.stderr | 6 ++--- .../macros/macro-at-most-once-rep-2018.stderr | 22 +++++++++---------- src/test/ui/macros/macro-non-lifetime.stderr | 2 +- src/test/ui/macros/missing-comma.stderr | 8 +++---- .../ui/macros/nonterminal-matching.stderr | 2 +- src/test/ui/macros/trace_faulty_macros.stderr | 2 +- .../parser/macro/macro-doc-comments-1.stderr | 2 +- .../parser/macro/macro-doc-comments-2.stderr | 2 +- src/test/ui/underscore-ident-matcher.stderr | 2 +- .../ui/vec/vec-macro-with-comma-only.stderr | 2 +- 20 files changed, 57 insertions(+), 45 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 26604c46be5..8fd9590a664 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -281,7 +281,7 @@ pub enum ParseResult { Success(T), /// Arm failed to match. If the second parameter is `token::Eof`, it indicates an unexpected /// end of macro invocation. Otherwise, it indicates that no rules expected the given token. - Failure(syntax_pos::Span, Token), + Failure(syntax_pos::Span, Token, String), /// Fatal error (malformed macro?). Abort compilation. Error(syntax_pos::Span, String), } @@ -698,7 +698,7 @@ pub fn parse( parser.span, ) { Success(_) => {} - Failure(sp, tok) => return Failure(sp, tok), + Failure(sp, tok, t) => return Failure(sp, tok, t), Error(sp, msg) => return Error(sp, msg), } @@ -710,7 +710,7 @@ pub fn parse( // Error messages here could be improved with links to original rules. // If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise, - // either the parse is ambiguous (which should never happen) or their is a syntax error. + // either the parse is ambiguous (which should never happen) or there is a syntax error. if token_name_eq(&parser.token, &token::Eof) { if eof_items.len() == 1 { let matches = eof_items[0] @@ -731,6 +731,7 @@ pub fn parse( sess.source_map().next_point(parser.span) }, token::Eof, + "missing tokens in macro arguments".to_string(), ); } } @@ -766,7 +767,11 @@ pub fn parse( // If there are no possible next positions AND we aren't waiting for the black-box parser, // then there is a syntax error. else if bb_items.is_empty() && next_items.is_empty() { - return Failure(parser.span, parser.token); + return Failure( + parser.span, + parser.token, + "no rules expected this token in macro call".to_string(), + ); } // Dump all possible `next_items` into `cur_items` for the next iteration. else if !next_items.is_empty() { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 04f145ce32f..5ce50f187d0 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -11,6 +11,7 @@ use {ast, attr}; use syntax_pos::{Span, DUMMY_SP}; use edition::Edition; +use errors::FatalError; use ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension}; use ext::base::{NormalTT, TTMacroExpander}; use ext::expand::{AstFragment, AstFragmentKind}; @@ -130,6 +131,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt, // Which arm's failure should we report? (the one furthest along) let mut best_fail_spot = DUMMY_SP; let mut best_fail_tok = None; + let mut best_fail_text = None; for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers let lhs_tt = match *lhs { @@ -185,9 +187,10 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt, macro_ident: name }) } - Failure(sp, tok) => if sp.lo() >= best_fail_spot.lo() { + Failure(sp, tok, t) => if sp.lo() >= best_fail_spot.lo() { best_fail_spot = sp; best_fail_tok = Some(tok); + best_fail_text = Some(t); }, Error(err_sp, ref msg) => { cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..]) @@ -198,7 +201,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt, let best_fail_msg = parse_failure_msg(best_fail_tok.expect("ran no matchers")); let span = best_fail_spot.substitute_dummy(sp); let mut err = cx.struct_span_err(span, &best_fail_msg); - err.span_label(span, best_fail_msg); + err.span_label(span, best_fail_text.unwrap_or(best_fail_msg)); if let Some(sp) = def_span { if cx.source_map().span_to_filename(sp).is_real() && !sp.is_dummy() { err.span_label(cx.source_map().def_span(sp), "when calling this macro"); @@ -278,9 +281,13 @@ pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item, edition: let argument_map = match parse(sess, body.stream(), &argument_gram, None, true) { Success(m) => m, - Failure(sp, tok) => { + Failure(sp, tok, t) => { let s = parse_failure_msg(tok); - sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s).raise(); + let sp = sp.substitute_dummy(def.span); + let mut err = sess.span_diagnostic.struct_span_fatal(sp, &s); + err.span_label(sp, t); + err.emit(); + FatalError.raise(); } Error(sp, s) => { sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s).raise(); diff --git a/src/test/ui/editions/edition-keywords-2015-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2015-2015-parsing.stderr index e8f05cbb0ef..8bf8c3c3560 100644 --- a/src/test/ui/editions/edition-keywords-2015-2015-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2015-2015-parsing.stderr @@ -2,13 +2,13 @@ error: no rules expected the token `r#async` --> $DIR/edition-keywords-2015-2015-parsing.rs:22:31 | LL | r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async` - | ^^^^^^^ no rules expected the token `r#async` + | ^^^^^^^ no rules expected this token in macro call error: no rules expected the token `async` --> $DIR/edition-keywords-2015-2015-parsing.rs:23:35 | LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` - | ^^^^^ no rules expected the token `async` + | ^^^^^ no rules expected this token in macro call error: aborting due to 2 previous errors diff --git a/src/test/ui/editions/edition-keywords-2015-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2015-2018-parsing.stderr index 3f5e1137383..77622548bce 100644 --- a/src/test/ui/editions/edition-keywords-2015-2018-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2015-2018-parsing.stderr @@ -2,13 +2,13 @@ error: no rules expected the token `r#async` --> $DIR/edition-keywords-2015-2018-parsing.rs:22:31 | LL | r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async` - | ^^^^^^^ no rules expected the token `r#async` + | ^^^^^^^ no rules expected this token in macro call error: no rules expected the token `async` --> $DIR/edition-keywords-2015-2018-parsing.rs:23:35 | LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` - | ^^^^^ no rules expected the token `async` + | ^^^^^ no rules expected this token in macro call error: aborting due to 2 previous errors diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr index bf7fc28c758..ad5794c75d3 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -14,13 +14,13 @@ error: no rules expected the token `r#async` --> $DIR/edition-keywords-2018-2015-parsing.rs:22:31 | LL | r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async` - | ^^^^^^^ no rules expected the token `r#async` + | ^^^^^^^ no rules expected this token in macro call error: no rules expected the token `async` --> $DIR/edition-keywords-2018-2015-parsing.rs:23:35 | LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` - | ^^^^^ no rules expected the token `async` + | ^^^^^ no rules expected this token in macro call error: expected one of `move`, `|`, or `||`, found the end of the macro arm --> <::edition_kw_macro_2015::passes_ident macros>:1:25 diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr index 4ab29ba67a0..c86817d482b 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -14,13 +14,13 @@ error: no rules expected the token `r#async` --> $DIR/edition-keywords-2018-2018-parsing.rs:22:31 | LL | r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async` - | ^^^^^^^ no rules expected the token `r#async` + | ^^^^^^^ no rules expected this token in macro call error: no rules expected the token `async` --> $DIR/edition-keywords-2018-2018-parsing.rs:23:35 | LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` - | ^^^^^ no rules expected the token `async` + | ^^^^^ no rules expected this token in macro call error: expected one of `move`, `|`, or `||`, found the end of the macro arm --> <::edition_kw_macro_2018::passes_ident macros>:1:25 diff --git a/src/test/ui/empty/empty-comment.stderr b/src/test/ui/empty/empty-comment.stderr index de826102081..d1b031c1f6c 100644 --- a/src/test/ui/empty/empty-comment.stderr +++ b/src/test/ui/empty/empty-comment.stderr @@ -5,7 +5,7 @@ LL | macro_rules! one_arg_macro { | -------------------------- when calling this macro ... LL | one_arg_macro!(/**/); //~ ERROR unexpected end - | ^^^^^^^^^^^^^^^^^^^^^ unexpected end of macro invocation + | ^^^^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments error: aborting due to previous error diff --git a/src/test/ui/fail-simple.stderr b/src/test/ui/fail-simple.stderr index 4a4aec5b6ac..9759249342a 100644 --- a/src/test/ui/fail-simple.stderr +++ b/src/test/ui/fail-simple.stderr @@ -2,7 +2,7 @@ error: no rules expected the token `@` --> $DIR/fail-simple.rs:12:12 | LL | panic!(@); //~ ERROR no rules expected the token `@` - | ^ no rules expected the token `@` + | ^ no rules expected this token in macro call error: aborting due to previous error diff --git a/src/test/ui/issues/issue-7970a.stderr b/src/test/ui/issues/issue-7970a.stderr index 96fb374b58c..2e2e869199c 100644 --- a/src/test/ui/issues/issue-7970a.stderr +++ b/src/test/ui/issues/issue-7970a.stderr @@ -5,7 +5,7 @@ LL | macro_rules! one_arg_macro { | -------------------------- when calling this macro ... LL | one_arg_macro!(); - | ^^^^^^^^^^^^^^^^^ unexpected end of macro invocation + | ^^^^^^^^^^^^^^^^^ missing tokens in macro arguments error: aborting due to previous error diff --git a/src/test/ui/issues/issue-7970b.stderr b/src/test/ui/issues/issue-7970b.stderr index b2feb677863..d49544e6c1e 100644 --- a/src/test/ui/issues/issue-7970b.stderr +++ b/src/test/ui/issues/issue-7970b.stderr @@ -2,7 +2,7 @@ error: unexpected end of macro invocation --> $DIR/issue-7970b.rs:13:1 | LL | macro_rules! test {} - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments error: aborting due to previous error diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.stderr b/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.stderr index 7705ba3b11e..27dc03e1c39 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.stderr +++ b/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.stderr @@ -55,7 +55,7 @@ LL | macro_rules! foo { | ---------------- when calling this macro ... LL | foo!(a?); //~ ERROR no rules expected the token `?` - | ^ no rules expected the token `?` + | ^ no rules expected this token in macro call error: no rules expected the token `?` --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:42:11 @@ -64,7 +64,7 @@ LL | macro_rules! foo { | ---------------- when calling this macro ... LL | foo!(a?a); //~ ERROR no rules expected the token `?` - | ^ no rules expected the token `?` + | ^ no rules expected this token in macro call error: no rules expected the token `?` --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:43:11 @@ -73,7 +73,7 @@ LL | macro_rules! foo { | ---------------- when calling this macro ... LL | foo!(a?a?a); //~ ERROR no rules expected the token `?` - | ^ no rules expected the token `?` + | ^ no rules expected this token in macro call error: aborting due to 10 previous errors diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr index 19a9cf3a6f5..d363b672680 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr +++ b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr @@ -11,7 +11,7 @@ LL | macro_rules! foo { | ---------------- when calling this macro ... LL | foo!(a?); //~ ERROR no rules expected the token `?` - | ^ no rules expected the token `?` + | ^ no rules expected this token in macro call error: no rules expected the token `?` --> $DIR/macro-at-most-once-rep-2018.rs:37:11 @@ -20,7 +20,7 @@ LL | macro_rules! foo { | ---------------- when calling this macro ... LL | foo!(a?a); //~ ERROR no rules expected the token `?` - | ^ no rules expected the token `?` + | ^ no rules expected this token in macro call error: no rules expected the token `?` --> $DIR/macro-at-most-once-rep-2018.rs:38:11 @@ -29,7 +29,7 @@ LL | macro_rules! foo { | ---------------- when calling this macro ... LL | foo!(a?a?a); //~ ERROR no rules expected the token `?` - | ^ no rules expected the token `?` + | ^ no rules expected this token in macro call error: unexpected end of macro invocation --> $DIR/macro-at-most-once-rep-2018.rs:40:5 @@ -38,7 +38,7 @@ LL | macro_rules! barplus { | -------------------- when calling this macro ... LL | barplus!(); //~ERROR unexpected end of macro invocation - | ^^^^^^^^^^^ unexpected end of macro invocation + | ^^^^^^^^^^^ missing tokens in macro arguments error: unexpected end of macro invocation --> $DIR/macro-at-most-once-rep-2018.rs:41:15 @@ -47,7 +47,7 @@ LL | macro_rules! barplus { | -------------------- when calling this macro ... LL | barplus!(a); //~ERROR unexpected end of macro invocation - | ^ unexpected end of macro invocation + | ^ missing tokens in macro arguments error: no rules expected the token `?` --> $DIR/macro-at-most-once-rep-2018.rs:42:15 @@ -56,7 +56,7 @@ LL | macro_rules! barplus { | -------------------- when calling this macro ... LL | barplus!(a?); //~ ERROR no rules expected the token `?` - | ^ no rules expected the token `?` + | ^ no rules expected this token in macro call error: no rules expected the token `?` --> $DIR/macro-at-most-once-rep-2018.rs:43:15 @@ -65,7 +65,7 @@ LL | macro_rules! barplus { | -------------------- when calling this macro ... LL | barplus!(a?a); //~ ERROR no rules expected the token `?` - | ^ no rules expected the token `?` + | ^ no rules expected this token in macro call error: unexpected end of macro invocation --> $DIR/macro-at-most-once-rep-2018.rs:47:5 @@ -74,7 +74,7 @@ LL | macro_rules! barstar { | -------------------- when calling this macro ... LL | barstar!(); //~ERROR unexpected end of macro invocation - | ^^^^^^^^^^^ unexpected end of macro invocation + | ^^^^^^^^^^^ missing tokens in macro arguments error: unexpected end of macro invocation --> $DIR/macro-at-most-once-rep-2018.rs:48:15 @@ -83,7 +83,7 @@ LL | macro_rules! barstar { | -------------------- when calling this macro ... LL | barstar!(a); //~ERROR unexpected end of macro invocation - | ^ unexpected end of macro invocation + | ^ missing tokens in macro arguments error: no rules expected the token `?` --> $DIR/macro-at-most-once-rep-2018.rs:49:15 @@ -92,7 +92,7 @@ LL | macro_rules! barstar { | -------------------- when calling this macro ... LL | barstar!(a?); //~ ERROR no rules expected the token `?` - | ^ no rules expected the token `?` + | ^ no rules expected this token in macro call error: no rules expected the token `?` --> $DIR/macro-at-most-once-rep-2018.rs:50:15 @@ -101,7 +101,7 @@ LL | macro_rules! barstar { | -------------------- when calling this macro ... LL | barstar!(a?a); //~ ERROR no rules expected the token `?` - | ^ no rules expected the token `?` + | ^ no rules expected this token in macro call error: aborting due to 12 previous errors diff --git a/src/test/ui/macros/macro-non-lifetime.stderr b/src/test/ui/macros/macro-non-lifetime.stderr index d526023d441..df9db06ca19 100644 --- a/src/test/ui/macros/macro-non-lifetime.stderr +++ b/src/test/ui/macros/macro-non-lifetime.stderr @@ -5,7 +5,7 @@ LL | macro_rules! m { ($x:lifetime) => { } } | -------------- when calling this macro ... LL | m!(a); - | ^ no rules expected the token `a` + | ^ no rules expected this token in macro call error: aborting due to previous error diff --git a/src/test/ui/macros/missing-comma.stderr b/src/test/ui/macros/missing-comma.stderr index 1d6af44bd08..886e15c4412 100644 --- a/src/test/ui/macros/missing-comma.stderr +++ b/src/test/ui/macros/missing-comma.stderr @@ -11,7 +11,7 @@ LL | macro_rules! foo { | ---------------- when calling this macro ... LL | foo!(a b); - | -^ no rules expected the token `b` + | -^ no rules expected this token in macro call | | | help: missing comma here @@ -22,7 +22,7 @@ LL | macro_rules! foo { | ---------------- when calling this macro ... LL | foo!(a, b, c, d e); - | -^ no rules expected the token `e` + | -^ no rules expected this token in macro call | | | help: missing comma here @@ -33,7 +33,7 @@ LL | macro_rules! foo { | ---------------- when calling this macro ... LL | foo!(a, b, c d, e); - | -^ no rules expected the token `d` + | -^ no rules expected this token in macro call | | | help: missing comma here @@ -44,7 +44,7 @@ LL | macro_rules! foo { | ---------------- when calling this macro ... LL | foo!(a, b, c d e); - | ^ no rules expected the token `d` + | ^ no rules expected this token in macro call error: aborting due to 5 previous errors diff --git a/src/test/ui/macros/nonterminal-matching.stderr b/src/test/ui/macros/nonterminal-matching.stderr index 23853978d37..9dfa53dab55 100644 --- a/src/test/ui/macros/nonterminal-matching.stderr +++ b/src/test/ui/macros/nonterminal-matching.stderr @@ -2,7 +2,7 @@ error: no rules expected the token `enum E { }` --> $DIR/nonterminal-matching.rs:29:10 | LL | n!(a $nt_item b); //~ ERROR no rules expected the token `enum E { }` - | ^^^^^^^^ no rules expected the token `enum E { }` + | ^^^^^^^^ no rules expected this token in macro call ... LL | complex_nonterminal!(enum E {}); | -------------------------------- in this macro invocation diff --git a/src/test/ui/macros/trace_faulty_macros.stderr b/src/test/ui/macros/trace_faulty_macros.stderr index 853eb5847c0..f524ebb3216 100644 --- a/src/test/ui/macros/trace_faulty_macros.stderr +++ b/src/test/ui/macros/trace_faulty_macros.stderr @@ -5,7 +5,7 @@ LL | macro_rules! my_faulty_macro { | ---------------------------- when calling this macro LL | () => { LL | my_faulty_macro!(bcd); //~ ERROR no rules - | ^^^ no rules expected the token `bcd` + | ^^^ no rules expected this token in macro call ... LL | my_faulty_macro!(); | ------------------- in this macro invocation diff --git a/src/test/ui/parser/macro/macro-doc-comments-1.stderr b/src/test/ui/parser/macro/macro-doc-comments-1.stderr index 1e765dcde4f..c40a7badaac 100644 --- a/src/test/ui/parser/macro/macro-doc-comments-1.stderr +++ b/src/test/ui/parser/macro/macro-doc-comments-1.stderr @@ -5,7 +5,7 @@ LL | macro_rules! outer { | ------------------ when calling this macro ... LL | //! Inner - | ^^^^^^^^^ no rules expected the token `!` + | ^^^^^^^^^ no rules expected this token in macro call error: aborting due to previous error diff --git a/src/test/ui/parser/macro/macro-doc-comments-2.stderr b/src/test/ui/parser/macro/macro-doc-comments-2.stderr index 0ab8a3cafb5..7bdd432808c 100644 --- a/src/test/ui/parser/macro/macro-doc-comments-2.stderr +++ b/src/test/ui/parser/macro/macro-doc-comments-2.stderr @@ -5,7 +5,7 @@ LL | macro_rules! inner { | ------------------ when calling this macro ... LL | /// Outer - | ^ no rules expected the token `[` + | ^ no rules expected this token in macro call error: aborting due to previous error diff --git a/src/test/ui/underscore-ident-matcher.stderr b/src/test/ui/underscore-ident-matcher.stderr index e148c48ed13..171e81e2d87 100644 --- a/src/test/ui/underscore-ident-matcher.stderr +++ b/src/test/ui/underscore-ident-matcher.stderr @@ -5,7 +5,7 @@ LL | macro_rules! identity { | --------------------- when calling this macro ... LL | let identity!(_) = 10; //~ ERROR no rules expected the token `_` - | ^ no rules expected the token `_` + | ^ no rules expected this token in macro call error: aborting due to previous error diff --git a/src/test/ui/vec/vec-macro-with-comma-only.stderr b/src/test/ui/vec/vec-macro-with-comma-only.stderr index 856d85ef5cd..74f5d2326ac 100644 --- a/src/test/ui/vec/vec-macro-with-comma-only.stderr +++ b/src/test/ui/vec/vec-macro-with-comma-only.stderr @@ -2,7 +2,7 @@ error: no rules expected the token `,` --> $DIR/vec-macro-with-comma-only.rs:12:10 | LL | vec![,]; //~ ERROR no rules expected the token `,` - | ^ no rules expected the token `,` + | ^ no rules expected this token in macro call error: aborting due to previous error From 76449d86c0c0b85ff93912a450012f2ece16c3d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 5 Nov 2018 12:25:31 -0800 Subject: [PATCH 0179/1984] Point at macro arm when it doesn't expand to an expression --- src/libsyntax/ext/tt/macro_rules.rs | 10 +++++++--- .../ui/macros/macro-in-expression-context-2.stderr | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 5ce50f187d0..fa10d219ad6 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -45,16 +45,18 @@ pub struct ParserAnyMacro<'a> { /// Span of the expansion site of the macro this parser is for site_span: Span, /// The ident of the macro we're parsing - macro_ident: ast::Ident + macro_ident: ast::Ident, + arm_span: Span, } impl<'a> ParserAnyMacro<'a> { pub fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { - let ParserAnyMacro { site_span, macro_ident, ref mut parser } = *self; + let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; let fragment = panictry!(parser.parse_ast_fragment(kind, true).map_err(|mut e| { if e.span.is_dummy() { // Get around lack of span in error (#30128) e.set_span(site_span); e.span_label(site_span, "in this macro expansion"); + e.span_label(arm_span, "in this macro arm"); } else if parser.token == token::Eof { // (#52866) e.set_span(parser.sess.source_map().next_point(parser.span)); } @@ -146,6 +148,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt, quoted::TokenTree::Delimited(_, ref delimed) => delimed.tts.clone(), _ => cx.span_bug(sp, "malformed macro rhs"), }; + let arm_span = rhses[i].span(); let rhs_spans = rhs.iter().map(|t| t.span()).collect::>(); // rhs has holes ( `$id` and `$(...)` that need filled) @@ -184,7 +187,8 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt, // so we can print a useful error message if the parse of the expanded // macro leaves unparsed tokens. site_span: sp, - macro_ident: name + macro_ident: name, + arm_span, }) } Failure(sp, tok, t) => if sp.lo() >= best_fail_spot.lo() { diff --git a/src/test/ui/macros/macro-in-expression-context-2.stderr b/src/test/ui/macros/macro-in-expression-context-2.stderr index 0d4f1e82663..f2b67ab6138 100644 --- a/src/test/ui/macros/macro-in-expression-context-2.stderr +++ b/src/test/ui/macros/macro-in-expression-context-2.stderr @@ -1,6 +1,9 @@ error: expected expression, found the end of the macro arm --> $DIR/macro-in-expression-context-2.rs:5:16 | +LL | macro_rules! empty { () => () } + | -- in this macro arm +... LL | _ => { empty!() } | ^^^^^^^^ in this macro expansion From c45871ba02430c3af6453d5636f8ad0afb7eb35f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 5 Nov 2018 16:27:28 -0800 Subject: [PATCH 0180/1984] Keep label on moved spans and point at macro invocation on parse error --- src/librustc_errors/diagnostic.rs | 11 ++++++++++ src/libsyntax/ext/tt/macro_rules.rs | 20 +++++++++++-------- .../directory_ownership/macro-expanded-mod.rs | 2 +- .../macro-expanded-mod.stderr | 6 +++--- .../edition-keywords-2018-2015-parsing.stderr | 7 ++++++- .../edition-keywords-2018-2018-parsing.stderr | 7 ++++++- .../macro-in-expression-context-2.stderr | 2 +- 7 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index a323282f233..ea425ad4c47 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -139,6 +139,17 @@ impl Diagnostic { self } + pub fn replace_span_with(&mut self, after: Span) -> &mut Self { + let before = self.span.clone(); + self.set_span(after); + for span_label in before.span_labels() { + if let Some(label) = span_label.label { + self.span_label(after, label); + } + } + self + } + pub fn note_expected_found(&mut self, label: &dyn fmt::Display, expected: DiagnosticStyledString, diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index fa10d219ad6..9f3a80b1151 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -53,20 +53,24 @@ impl<'a> ParserAnyMacro<'a> { pub fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; let fragment = panictry!(parser.parse_ast_fragment(kind, true).map_err(|mut e| { - if e.span.is_dummy() { // Get around lack of span in error (#30128) - e.set_span(site_span); - e.span_label(site_span, "in this macro expansion"); - e.span_label(arm_span, "in this macro arm"); - } else if parser.token == token::Eof { // (#52866) - e.set_span(parser.sess.source_map().next_point(parser.span)); - } - if parser.token == token::Eof { + if parser.token == token::Eof && e.message().ends_with(", found ``") { + if !e.span.is_dummy() { // early end of macro arm (#52866) + e.replace_span_with(parser.sess.source_map().next_point(parser.span)); + } let msg = &e.message[0]; e.message[0] = ( msg.0.replace(", found ``", ", found the end of the macro arm"), msg.1, ); } + if e.span.is_dummy() { // Get around lack of span in error (#30128) + e.replace_span_with(site_span); + if parser.sess.source_map().span_to_filename(arm_span).is_real() { + e.span_label(arm_span, "in this macro arm"); + } + } else if !parser.sess.source_map().span_to_filename(parser.span).is_real() { + e.span_label(site_span, "in this macro invocation"); + } e })); diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.rs b/src/test/ui/directory_ownership/macro-expanded-mod.rs index 78356f981fc..59ebc94f6de 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.rs +++ b/src/test/ui/directory_ownership/macro-expanded-mod.rs @@ -12,7 +12,6 @@ macro_rules! mod_decl { ($i:ident) => { mod $i; } - //~^ ERROR Cannot declare a non-inline module inside a block } mod macro_expanded_mod_helper { @@ -21,4 +20,5 @@ mod macro_expanded_mod_helper { fn main() { mod_decl!(foo); + //~^ ERROR Cannot declare a non-inline module inside a block } diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.stderr b/src/test/ui/directory_ownership/macro-expanded-mod.stderr index f58e864a755..43bf720083d 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.stderr +++ b/src/test/ui/directory_ownership/macro-expanded-mod.stderr @@ -1,8 +1,8 @@ error: Cannot declare a non-inline module inside a block unless it has a path attribute - --> $DIR/macro-expanded-mod.rs:14:28 + --> $DIR/macro-expanded-mod.rs:22:15 | -LL | ($i:ident) => { mod $i; } - | ^ +LL | mod_decl!(foo); + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr index ad5794c75d3..943183814f7 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -26,7 +26,12 @@ error: expected one of `move`, `|`, or `||`, found the end of the macro arm --> <::edition_kw_macro_2015::passes_ident macros>:1:25 | LL | ( $ i : ident ) => ( $ i ) - | ^ + | ^ expected one of `move`, `|`, or `||` here + | + ::: $DIR/edition-keywords-2018-2015-parsing.rs:26:8 + | +LL | if passes_ident!(async) == 1 {} + | -------------------- in this macro invocation error: aborting due to 5 previous errors diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr index c86817d482b..e7379988892 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -26,7 +26,12 @@ error: expected one of `move`, `|`, or `||`, found the end of the macro arm --> <::edition_kw_macro_2018::passes_ident macros>:1:25 | LL | ( $ i : ident ) => ( $ i ) - | ^ + | ^ expected one of `move`, `|`, or `||` here + | + ::: $DIR/edition-keywords-2018-2018-parsing.rs:26:8 + | +LL | if passes_ident!(async) == 1 {} + | -------------------- in this macro invocation error: aborting due to 5 previous errors diff --git a/src/test/ui/macros/macro-in-expression-context-2.stderr b/src/test/ui/macros/macro-in-expression-context-2.stderr index f2b67ab6138..f6e6ecf112a 100644 --- a/src/test/ui/macros/macro-in-expression-context-2.stderr +++ b/src/test/ui/macros/macro-in-expression-context-2.stderr @@ -5,7 +5,7 @@ LL | macro_rules! empty { () => () } | -- in this macro arm ... LL | _ => { empty!() } - | ^^^^^^^^ in this macro expansion + | ^^^^^^^^ expected expression error: aborting due to previous error From 950a3edf27bf3bad702b0f10ce771ae8bf7f58dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 5 Nov 2018 16:32:58 -0800 Subject: [PATCH 0181/1984] Fix proc-macro test after internal API change --- .../run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs index 2c5de332327..9f822834daf 100644 --- a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs +++ b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs @@ -46,8 +46,8 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree]) NodeId::from_u32(0)); let map = match TokenTree::parse(cx, &mbe_matcher, args.iter().cloned().collect()) { Success(map) => map, - Failure(_, tok) => { - panic!("expected Success, but got Failure: {}", parse_failure_msg(tok)); + Failure(_, tok, msg) => { + panic!("expected Success, but got Failure: {} - {}", parse_failure_msg(tok), msg); } Error(_, s) => { panic!("expected Success, but got Error: {}", s); From d011313d843b3ddcf095db06907abffdd9cc5904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 23 Nov 2018 15:37:27 -0800 Subject: [PATCH 0182/1984] Reword EOF in macro arm message --- src/libsyntax/ext/tt/macro_rules.rs | 5 ++++- .../ui/editions/edition-keywords-2018-2015-parsing.stderr | 2 +- .../ui/editions/edition-keywords-2018-2018-parsing.stderr | 2 +- src/test/ui/macros/macro-in-expression-context-2.stderr | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 9f3a80b1151..e731be578cd 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -59,7 +59,10 @@ impl<'a> ParserAnyMacro<'a> { } let msg = &e.message[0]; e.message[0] = ( - msg.0.replace(", found ``", ", found the end of the macro arm"), + format!( + "macro expansion ends with an incomplete expression: {}", + msg.0.replace(", found ``", ""), + ), msg.1, ); } diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr index 943183814f7..d0edc368ad5 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -22,7 +22,7 @@ error: no rules expected the token `async` LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` | ^^^^^ no rules expected this token in macro call -error: expected one of `move`, `|`, or `||`, found the end of the macro arm +error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||` --> <::edition_kw_macro_2015::passes_ident macros>:1:25 | LL | ( $ i : ident ) => ( $ i ) diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr index e7379988892..c4e1e0257c5 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -22,7 +22,7 @@ error: no rules expected the token `async` LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` | ^^^^^ no rules expected this token in macro call -error: expected one of `move`, `|`, or `||`, found the end of the macro arm +error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||` --> <::edition_kw_macro_2018::passes_ident macros>:1:25 | LL | ( $ i : ident ) => ( $ i ) diff --git a/src/test/ui/macros/macro-in-expression-context-2.stderr b/src/test/ui/macros/macro-in-expression-context-2.stderr index f6e6ecf112a..672871c49ca 100644 --- a/src/test/ui/macros/macro-in-expression-context-2.stderr +++ b/src/test/ui/macros/macro-in-expression-context-2.stderr @@ -1,4 +1,4 @@ -error: expected expression, found the end of the macro arm +error: macro expansion ends with an incomplete expression: expected expression --> $DIR/macro-in-expression-context-2.rs:5:16 | LL | macro_rules! empty { () => () } From 7401e3def59452e795468d4d5e4f30c7ef100fec Mon Sep 17 00:00:00 2001 From: scalexm Date: Fri, 2 Nov 2018 15:08:51 +0100 Subject: [PATCH 0183/1984] Distinguish between placeholder kinds --- src/librustc/infer/canonical/mod.rs | 6 +++--- src/librustc/infer/higher_ranked/mod.rs | 2 +- src/librustc/infer/mod.rs | 2 +- src/librustc/infer/nll_relate/mod.rs | 4 ++-- src/librustc/ty/mod.rs | 21 ++++++++++++++++--- src/librustc/ty/sty.rs | 2 +- src/librustc/util/ppaux.rs | 2 +- .../borrow_check/error_reporting.rs | 4 ++-- .../borrow_check/nll/region_infer/mod.rs | 2 +- .../borrow_check/nll/region_infer/values.rs | 18 ++++++++-------- .../borrow_check/nll/type_check/mod.rs | 2 +- .../borrow_check/nll/type_check/relate_tys.rs | 5 ++++- 12 files changed, 44 insertions(+), 26 deletions(-) diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index f7eb7118f41..41839d61d32 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -142,7 +142,7 @@ pub enum CanonicalVarKind { /// A "placeholder" that represents "any region". Created when you /// are solving a goal like `for<'a> T: Foo<'a>` to represent the /// bound region `'a`. - PlaceholderRegion(ty::Placeholder), + PlaceholderRegion(ty::PlaceholderRegion), } impl CanonicalVarKind { @@ -374,9 +374,9 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { universe_map(ui), ).into(), - CanonicalVarKind::PlaceholderRegion(ty::Placeholder { universe, name }) => { + CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, name }) => { let universe_mapped = universe_map(universe); - let placeholder_mapped = ty::Placeholder { + let placeholder_mapped = ty::PlaceholderRegion { universe: universe_mapped, name, }; diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index 8172f620c36..ddf46b18ef7 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -340,7 +340,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let next_universe = self.create_next_universe(); let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| { - self.tcx.mk_region(ty::RePlaceholder(ty::Placeholder { + self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion { universe: next_universe, name: br, })) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 87e32be1a17..dfe6aa160b3 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -411,7 +411,7 @@ pub enum NLLRegionVariableOrigin { /// "Universal" instantiation of a higher-ranked region (e.g., /// from a `for<'a> T` binder). Meant to represent "any region". - Placeholder(ty::Placeholder), + Placeholder(ty::PlaceholderRegion), Existential, } diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs index e003c1989e0..9bdbf77fee0 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -95,7 +95,7 @@ pub trait TypeRelatingDelegate<'tcx> { /// So e.g. if you have `for<'a> fn(..) <: for<'b> fn(..)`, then /// we will invoke this method to instantiate `'b` with a /// placeholder region. - fn next_placeholder_region(&mut self, placeholder: ty::Placeholder) -> ty::Region<'tcx>; + fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx>; /// Creates a new existential region in the given universe. This /// is used when handling subtyping and type variables -- if we @@ -176,7 +176,7 @@ where universe }); - let placeholder = ty::Placeholder { universe, name: br }; + let placeholder = ty::PlaceholderRegion { universe, name: br }; delegate.next_placeholder_region(placeholder) } else { delegate.next_existential_region_var() diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index ad200449f89..4372beafa64 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1587,12 +1587,27 @@ impl UniverseIndex { /// universe are just two regions with an unknown relationship to one /// another. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)] -pub struct Placeholder { +pub struct Placeholder { pub universe: UniverseIndex, - pub name: BoundRegion, + pub name: T, } -impl_stable_hash_for!(struct Placeholder { universe, name }); +impl<'a, 'gcx, T> HashStable> for Placeholder + where T: HashStable> +{ + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher + ) { + self.universe.hash_stable(hcx, hasher); + self.name.hash_stable(hcx, hasher); + } +} + +pub type PlaceholderRegion = Placeholder; + +pub type PlaceholderType = Placeholder; /// When type checking, we use the `ParamEnv` to track /// details about the set of where-clauses that are in scope at this diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index bd3a34cae90..5c01f1cc3e4 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1165,7 +1165,7 @@ pub enum RegionKind { /// A placeholder region - basically the higher-ranked version of ReFree. /// Should not exist after typeck. - RePlaceholder(ty::Placeholder), + RePlaceholder(ty::PlaceholderRegion), /// Empty lifetime is for data that is never accessed. /// Bottom in the region lattice. We treat ReEmpty somewhat diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index d53370d242b..613a0dbc61f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -792,7 +792,7 @@ define_print! { } ty::ReLateBound(_, br) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | - ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { + ty::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => { write!(f, "{}", br) } ty::ReScope(scope) if cx.identify_regions => { diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 3c4d8e09fc1..4ccd26bee8b 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -2193,7 +2193,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { match ty.sty { ty::TyKind::Ref(ty::RegionKind::ReLateBound(_, br), _, _) | ty::TyKind::Ref( - ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }), + ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }), _, _, ) => with_highlight_region_for_bound_region(*br, counter, || ty.to_string()), @@ -2207,7 +2207,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { match ty.sty { ty::TyKind::Ref(region, _, _) => match region { ty::RegionKind::ReLateBound(_, br) - | ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }) => { + | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => { with_highlight_region_for_bound_region(*br, counter, || region.to_string()) } _ => region.to_string(), diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 376f4459242..6a1dc50c67a 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -1230,7 +1230,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { mir: &Mir<'tcx>, _mir_def_id: DefId, longer_fr: RegionVid, - placeholder: ty::Placeholder, + placeholder: ty::PlaceholderRegion, ) { debug!( "check_bound_universal_region(fr={:?}, placeholder={:?})", diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index 2b7ef38d3ed..69e2c896d33 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -150,7 +150,7 @@ crate enum RegionElement { /// A placeholder (e.g., instantiated from a `for<'a> fn(&'a u32)` /// type). - PlaceholderRegion(ty::Placeholder), + PlaceholderRegion(ty::PlaceholderRegion), } /// When we initially compute liveness, we use a bit matrix storing @@ -219,17 +219,17 @@ impl LivenessValues { } } -/// Maps from `ty::Placeholder` values that are used in the rest of +/// Maps from `ty::PlaceholderRegion` values that are used in the rest of /// rustc to the internal `PlaceholderIndex` values that are used in /// NLL. #[derive(Default)] crate struct PlaceholderIndices { - to_index: FxHashMap, - from_index: IndexVec, + to_index: FxHashMap, + from_index: IndexVec, } impl PlaceholderIndices { - crate fn insert(&mut self, placeholder: ty::Placeholder) -> PlaceholderIndex { + crate fn insert(&mut self, placeholder: ty::PlaceholderRegion) -> PlaceholderIndex { let PlaceholderIndices { to_index, from_index, @@ -239,11 +239,11 @@ impl PlaceholderIndices { .or_insert_with(|| from_index.push(placeholder)) } - crate fn lookup_index(&self, placeholder: ty::Placeholder) -> PlaceholderIndex { + crate fn lookup_index(&self, placeholder: ty::PlaceholderRegion) -> PlaceholderIndex { self.to_index[&placeholder] } - crate fn lookup_placeholder(&self, placeholder: PlaceholderIndex) -> ty::Placeholder { + crate fn lookup_placeholder(&self, placeholder: PlaceholderIndex) -> ty::PlaceholderRegion { self.from_index[placeholder] } @@ -375,7 +375,7 @@ impl RegionValues { crate fn placeholders_contained_in<'a>( &'a self, r: N, - ) -> impl Iterator + 'a { + ) -> impl Iterator + 'a { self.placeholders .row(r) .into_iter() @@ -432,7 +432,7 @@ impl ToElementIndex for RegionVid { } } -impl ToElementIndex for ty::Placeholder { +impl ToElementIndex for ty::PlaceholderRegion { fn add_to_row(self, values: &mut RegionValues, row: N) -> bool { let index = values.placeholder_indices.lookup_index(self); values.placeholders.insert(row, index) diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 06dfd4bc2cc..6f4d8c2bef9 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -777,7 +777,7 @@ impl MirTypeckRegionConstraints<'tcx> { fn placeholder_region( &mut self, infcx: &InferCtxt<'_, '_, 'tcx>, - placeholder: ty::Placeholder, + placeholder: ty::PlaceholderRegion, ) -> ty::Region<'tcx> { let placeholder_index = self.placeholder_indices.insert(placeholder); match self.placeholder_index_to_region.get(placeholder_index) { diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs index b82efb29f6e..cf4f9130807 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs @@ -84,7 +84,10 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, '_, 'tcx> { } } - fn next_placeholder_region(&mut self, placeholder: ty::Placeholder) -> ty::Region<'tcx> { + fn next_placeholder_region( + &mut self, + placeholder: ty::PlaceholderRegion + ) -> ty::Region<'tcx> { if let Some(borrowck_context) = &mut self.borrowck_context { borrowck_context.constraints.placeholder_region(self.infcx, placeholder) } else { From 05995a85221cde573b81ab918b0f3686452dca3b Mon Sep 17 00:00:00 2001 From: scalexm Date: Fri, 2 Nov 2018 18:48:24 +0100 Subject: [PATCH 0184/1984] Introduce `TyKind::Placeholder` variant --- src/librustc/ich/impls_ty.rs | 3 +++ src/librustc/infer/canonical/canonicalizer.rs | 1 + src/librustc/infer/freshen.rs | 6 +++--- src/librustc/traits/coherence.rs | 2 +- src/librustc/traits/error_reporting.rs | 2 +- src/librustc/traits/query/dropck_outlives.rs | 1 + src/librustc/traits/select.rs | 3 +++ src/librustc/ty/context.rs | 2 +- src/librustc/ty/error.rs | 1 + src/librustc/ty/fast_reject.rs | 2 +- src/librustc/ty/flags.rs | 1 + src/librustc/ty/item_path.rs | 1 + src/librustc/ty/layout.rs | 4 +++- src/librustc/ty/mod.rs | 1 + src/librustc/ty/outlives.rs | 1 + src/librustc/ty/structural_impls.rs | 2 ++ src/librustc/ty/sty.rs | 5 +++++ src/librustc/ty/util.rs | 2 +- src/librustc/ty/walk.rs | 2 +- src/librustc/ty/wf.rs | 1 + src/librustc/util/ppaux.rs | 5 ++++- src/librustc_codegen_llvm/debuginfo/type_names.rs | 1 + src/librustc_lint/types.rs | 1 + src/librustc_mir/monomorphize/item.rs | 1 + src/librustc_traits/chalk_context/program_clauses.rs | 1 + src/librustc_traits/dropck_outlives.rs | 2 +- src/librustc_traits/lowering/environment.rs | 1 + src/librustc_typeck/check/cast.rs | 2 +- src/librustc_typeck/variance/constraints.rs | 1 + src/librustdoc/clean/mod.rs | 1 + 30 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 679107160a6..4b465c7ad54 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -687,6 +687,9 @@ for ty::TyKind<'gcx> Bound(bound_ty) => { bound_ty.hash_stable(hcx, hasher); } + ty::Placeholder(placeholder_ty) => { + placeholder_ty.hash_stable(hcx, hasher); + } Foreign(def_id) => { def_id.hash_stable(hcx, hasher); } diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index a787eeae663..a3cbae2ff71 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -380,6 +380,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> | ty::Never | ty::Tuple(..) | ty::Projection(..) + | ty::Placeholder(..) | ty::UnnormalizedProjection(..) | ty::Foreign(..) | ty::Param(..) diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index b53444992fa..d17cf0c7b47 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -170,9 +170,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { t } - ty::Bound(..) => - bug!("encountered bound ty during freshening"), - ty::Generator(..) | ty::Bool | ty::Char | @@ -200,6 +197,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { ty::Opaque(..) => { t.super_fold_with(self) } + + ty::Placeholder(..) | + ty::Bound(..) => bug!("unexpected type {:?}", t), } } } diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 71b77909b82..b7a84c99308 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -455,7 +455,7 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool { false } - ty::Bound(..) | ty::Infer(..) => match in_crate { + ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) => match in_crate { InCrate::Local => false, // The inference variable might be unified with a local // type in that remote crate. diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 48b2b25d6ad..7e97dc3c84a 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -281,7 +281,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::Generator(..) => Some(18), ty::Foreign(..) => Some(19), ty::GeneratorWitness(..) => Some(20), - ty::Bound(..) | ty::Infer(..) | ty::Error => None, + ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None, ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), } } diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index 99dc099d577..b8bf0fcc153 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -251,6 +251,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> | ty::Projection(..) | ty::Param(_) | ty::Opaque(..) + | ty::Placeholder(..) | ty::Infer(_) | ty::Bound(..) | ty::Generator(..) => false, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 550c27ca0ab..6a91ad59d98 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2470,6 +2470,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::Infer(ty::TyVar(_)) => Ambiguous, ty::UnnormalizedProjection(..) + | ty::Placeholder(..) | ty::Bound(_) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) @@ -2555,6 +2556,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } ty::UnnormalizedProjection(..) + | ty::Placeholder(..) | ty::Bound(_) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) @@ -2594,6 +2596,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { | ty::Char => Vec::new(), ty::UnnormalizedProjection(..) + | ty::Placeholder(..) | ty::Dynamic(..) | ty::Param(..) | ty::Foreign(..) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a8ce52a8e15..d9d1b81fd8f 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2250,7 +2250,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { pub fn print_debug_stats(self) { sty_debug_print!( self, - Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr, + Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr, Placeholder, Generator, GeneratorWitness, Dynamic, Closure, Tuple, Bound, Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign); diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 4737c72b1ef..e78759e3e79 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -212,6 +212,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::Infer(ty::TyVar(_)) => "inferred type".into(), ty::Infer(ty::IntVar(_)) => "integral variable".into(), ty::Infer(ty::FloatVar(_)) => "floating-point variable".into(), + ty::Placeholder(..) => "placeholder type".into(), ty::Bound(_) | ty::Infer(ty::FreshTy(_)) => "fresh type".into(), ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(), diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 380f95993f8..8304e363815 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -122,7 +122,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::Foreign(def_id) => { Some(ForeignSimplifiedType(def_id)) } - ty::Bound(..) | ty::Infer(_) | ty::Error => None, + ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) | ty::Error => None, } } diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 0764f363250..9cdeb300393 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -74,6 +74,7 @@ impl FlagComputation { &ty::Uint(_) | &ty::Never | &ty::Str | + &ty::Placeholder(..) | &ty::Foreign(..) => { } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index d44ba030841..f6c90ab0a1a 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -515,6 +515,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { ty::Str | ty::FnPtr(_) | ty::Projection(_) | + ty::Placeholder(..) | ty::UnnormalizedProjection(..) | ty::Param(_) | ty::Opaque(..) | diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index da0a9acede2..5406495226d 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1159,6 +1159,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } ty::Bound(..) | + ty::Placeholder(..) | ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | ty::Infer(_) => { @@ -1743,7 +1744,8 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } ty::Projection(_) | ty::UnnormalizedProjection(..) | ty::Bound(..) | - ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error => { + ty::Placeholder(..) | ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | + ty::Error => { bug!("TyLayout::field_type: unexpected type `{}`", this.ty) } }) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4372beafa64..baedbc82149 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2445,6 +2445,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } + Placeholder(..) | Bound(..) | Infer(..) => { bug!("unexpected type `{:?}` in sized_constraint_for_ty", diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index 7fac88a3d78..0e3fc62e4ca 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -155,6 +155,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::FnDef(..) | // OutlivesFunction (*) ty::FnPtr(_) | // OutlivesFunction (*) ty::Dynamic(..) | // OutlivesObject, OutlivesFragment (*) + ty::Placeholder(..) | ty::Bound(..) | ty::Error => { // (*) Bare functions and traits are both binders. In the diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index e92f92dce63..d6aeb288b5c 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -746,6 +746,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::Infer(_) | ty::Param(..) | ty::Bound(..) | + ty::Placeholder(..) | ty::Never | ty::Foreign(..) => return self }; @@ -792,6 +793,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::Error | ty::Infer(_) | ty::Bound(..) | + ty::Placeholder(..) | ty::Param(..) | ty::Never | ty::Foreign(..) => false, diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 5c01f1cc3e4..7e6673a3dcd 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -203,6 +203,9 @@ pub enum TyKind<'tcx> { /// Bound type variable, used only when preparing a trait query. Bound(BoundTy), + /// A placeholder type - universally quantified higher-ranked type. + Placeholder(ty::PlaceholderType), + /// A type variable used during type checking. Infer(InferTy), @@ -1890,6 +1893,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { Foreign(..) | Param(_) | Bound(..) | + Placeholder(..) | Infer(_) | Error => {} } @@ -1954,6 +1958,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { ty::Infer(ty::TyVar(_)) => false, ty::Bound(_) | + ty::Placeholder(..) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) => diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 3d0c54d6b0a..f0885f96051 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -952,7 +952,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Can refer to a type which may drop. // FIXME(eddyb) check this against a ParamEnv. ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) | ty::Bound(..) | - ty::Opaque(..) | ty::Infer(_) | ty::Error => true, + ty::Placeholder(..) | ty::Opaque(..) | ty::Infer(_) | ty::Error => true, ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 284c595ee2d..82b95b9df60 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -82,7 +82,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { match parent_ty.sty { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Infer(_) | ty::Param(_) | ty::Never | ty::Error | - ty::Bound(..) | ty::Foreign(..) => { + ty::Placeholder(..) | ty::Bound(..) | ty::Foreign(..) => { } ty::Array(ty, len) => { push_const(stack, len); diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 1336eac63f8..6ae0793d924 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -259,6 +259,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { ty::Never | ty::Param(_) | ty::Bound(..) | + ty::Placeholder(..) | ty::Foreign(..) => { // WfScalar, WfParameter, etc } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 613a0dbc61f..0c424b34415 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -18,7 +18,7 @@ use ty::{Bool, Char, Adt}; use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; use ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; -use ty::{UnnormalizedProjection, Dynamic, Int, Uint, Infer}; +use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; use util::nodemap::FxHashSet; @@ -1144,6 +1144,9 @@ define_print! { data.print(f, cx)?; write!(f, ")") } + Placeholder(placeholder) => { + write!(f, "Placeholder({:?})", placeholder) + } Opaque(def_id, substs) => { if cx.is_verbose { return write!(f, "Opaque({:?}, {:?})", def_id, substs); diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs index c3a15ccca0a..60545f9e193 100644 --- a/src/librustc_codegen_llvm/debuginfo/type_names.rs +++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs @@ -172,6 +172,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } ty::Error | ty::Infer(_) | + ty::Placeholder(..) | ty::UnnormalizedProjection(..) | ty::Projection(..) | ty::Bound(..) | diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 0e2d041b1ff..82ace620c8a 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -727,6 +727,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) | + ty::Placeholder(..) | ty::UnnormalizedProjection(..) | ty::Projection(..) | ty::Opaque(..) | diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 9c90e5ffd3c..24de92e79f0 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -378,6 +378,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { ty::Error | ty::Bound(..) | ty::Infer(_) | + ty::Placeholder(..) | ty::UnnormalizedProjection(..) | ty::Projection(..) | ty::Param(_) | diff --git a/src/librustc_traits/chalk_context/program_clauses.rs b/src/librustc_traits/chalk_context/program_clauses.rs index 31f97b72e19..5592d2a583c 100644 --- a/src/librustc_traits/chalk_context/program_clauses.rs +++ b/src/librustc_traits/chalk_context/program_clauses.rs @@ -418,6 +418,7 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> { } ty::GeneratorWitness(..) | + ty::Placeholder(..) | ty::UnnormalizedProjection(..) | ty::Infer(..) | ty::Bound(..) | diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index af64522f183..9ab86daf654 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -274,7 +274,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>( ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), - ty::Bound(..) | ty::Infer(..) | ty::Error => { + ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => { // By the time this code runs, all type variables ought to // be fully resolved. Err(NoSolution) diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs index 54f0c6e8da7..c3573f47ceb 100644 --- a/src/librustc_traits/lowering/environment.rs +++ b/src/librustc_traits/lowering/environment.rs @@ -114,6 +114,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> { ty::Tuple(..) | ty::Never | ty::Infer(..) | + ty::Placeholder(..) | ty::Bound(..) => (), ty::GeneratorWitness(..) | diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 3f0a3531244..c35aee7883f 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -128,7 +128,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)), ty::Param(ref p) => Some(PointerKind::OfParam(p)), // Insufficient type information. - ty::Bound(..) | ty::Infer(_) => None, + ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => None, ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | ty::Float(_) | ty::Array(..) | ty::GeneratorWitness(..) | diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 47d34c90996..ed32e5a8d9b 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -336,6 +336,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // types, where we use Error as the Self type } + ty::Placeholder(..) | ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | ty::Bound(..) | diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0518d73e1e3..fd8f70b19e7 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2744,6 +2744,7 @@ impl<'tcx> Clean for Ty<'tcx> { ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton) ty::Bound(..) => panic!("Bound"), + ty::Placeholder(..) => panic!("Placeholder"), ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"), ty::GeneratorWitness(..) => panic!("GeneratorWitness"), ty::Infer(..) => panic!("Infer"), From da3def3ebffaefc4e8abbdba99981141ab74e4e4 Mon Sep 17 00:00:00 2001 From: scalexm Date: Fri, 2 Nov 2018 18:56:30 +0100 Subject: [PATCH 0185/1984] Rename some occurences of `skol` to `placeholder` --- src/librustc/traits/project.rs | 4 ++-- src/librustc/traits/query/normalize.rs | 2 +- src/librustc/ty/fold.rs | 8 ++++---- src/librustc/ty/mod.rs | 6 +++--- src/librustc/ty/sty.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/check/writeback.rs | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index b59bd0e2388..0aabb7ad713 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -424,7 +424,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, if let ConstValue::Unevaluated(def_id, substs) = constant.val { let tcx = self.selcx.tcx().global_tcx(); if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) { - if substs.needs_infer() || substs.has_skol() { + if substs.needs_infer() || substs.has_placeholders() { let identity_substs = Substs::identity_for_item(tcx, def_id); let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs); if let Some(instance) = instance { @@ -1656,7 +1656,7 @@ impl<'tcx> ProjectionCache<'tcx> { } pub fn rollback_placeholder(&mut self, snapshot: &ProjectionCacheSnapshot) { - self.map.partial_rollback(&snapshot.snapshot, &|k| k.ty.has_re_skol()); + self.map.partial_rollback(&snapshot.snapshot, &|k| k.ty.has_re_placeholders()); } pub fn commit(&mut self, snapshot: &ProjectionCacheSnapshot) { diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 59b086e35de..91b2ba301c3 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -202,7 +202,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx if let ConstValue::Unevaluated(def_id, substs) = constant.val { let tcx = self.infcx.tcx.global_tcx(); if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) { - if substs.needs_infer() || substs.has_skol() { + if substs.needs_infer() || substs.has_placeholders() { let identity_substs = Substs::identity_for_item(tcx, def_id); let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs); if let Some(instance) = instance { diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 2c781483145..9abc84e2a25 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -102,14 +102,14 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn needs_infer(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER) } - fn has_skol(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_SKOL) + fn has_placeholders(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_PLACEHOLDER) } fn needs_subst(&self) -> bool { self.has_type_flags(TypeFlags::NEEDS_SUBST) } - fn has_re_skol(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_SKOL) + fn has_re_placeholders(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_PLACEHOLDER) } fn has_closure_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_CLOSURE) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index baedbc82149..183aaadf6e6 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -432,7 +432,7 @@ bitflags! { const HAS_SELF = 1 << 1; const HAS_TY_INFER = 1 << 2; const HAS_RE_INFER = 1 << 3; - const HAS_RE_SKOL = 1 << 4; + const HAS_RE_PLACEHOLDER = 1 << 4; /// Does this have any `ReEarlyBound` regions? Used to /// determine whether substitition is required, since those @@ -478,7 +478,7 @@ bitflags! { TypeFlags::HAS_SELF.bits | TypeFlags::HAS_TY_INFER.bits | TypeFlags::HAS_RE_INFER.bits | - TypeFlags::HAS_RE_SKOL.bits | + TypeFlags::HAS_RE_PLACEHOLDER.bits | TypeFlags::HAS_RE_EARLY_BOUND.bits | TypeFlags::HAS_FREE_REGIONS.bits | TypeFlags::HAS_TY_ERR.bits | @@ -1689,7 +1689,7 @@ impl<'tcx> ParamEnv<'tcx> { } Reveal::All => { - if value.has_skol() + if value.has_placeholders() || value.needs_infer() || value.has_param_types() || value.has_self_ty() diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 7e6673a3dcd..cd69d31a004 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1465,7 +1465,7 @@ impl RegionKind { } ty::RePlaceholder(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_RE_SKOL; + flags = flags | TypeFlags::HAS_RE_PLACEHOLDER; } ty::ReLateBound(..) => { flags = flags | TypeFlags::HAS_RE_LATE_BOUND; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 0373bf4e752..5b67116cb51 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1494,7 +1494,7 @@ impl<'tcx> Candidate<'tcx> { // `WhereClausePick`. assert!( !trait_ref.skip_binder().substs.needs_infer() - && !trait_ref.skip_binder().substs.has_skol() + && !trait_ref.skip_binder().substs.has_placeholders() ); WhereClausePick(trait_ref.clone()) diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 50f54bba3fd..669f2bcb77c 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -115,7 +115,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'gcx>) { debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty); - assert!(!ty.needs_infer() && !ty.has_skol()); + assert!(!ty.needs_infer() && !ty.has_placeholders()); self.tables.node_types_mut().insert(hir_id, ty); } @@ -580,7 +580,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { if let Some(substs) = self.fcx.tables.borrow().node_substs_opt(hir_id) { let substs = self.resolve(&substs, &span); debug!("write_substs_to_tcx({:?}, {:?})", hir_id, substs); - assert!(!substs.needs_infer() && !substs.has_skol()); + assert!(!substs.needs_infer() && !substs.has_placeholders()); self.tables.node_substs_mut().insert(hir_id, substs); } From 91623ca6405b5e3c7736bcacb244718906d4aa69 Mon Sep 17 00:00:00 2001 From: scalexm Date: Fri, 2 Nov 2018 19:25:20 +0100 Subject: [PATCH 0186/1984] Add `HAS_TY_PLACEHOLDER` flag --- src/librustc/infer/canonical/canonicalizer.rs | 8 ++++++-- src/librustc/ty/flags.rs | 5 ++++- src/librustc/ty/fold.rs | 2 +- src/librustc/ty/mod.rs | 5 ++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index a3cbae2ff71..a9c6c3b5085 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -409,9 +409,13 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { V: TypeFoldable<'tcx> + Lift<'gcx>, { let needs_canonical_flags = if canonicalize_region_mode.any() { - TypeFlags::HAS_FREE_REGIONS | TypeFlags::KEEP_IN_LOCAL_TCX + TypeFlags::KEEP_IN_LOCAL_TCX | + TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS` + TypeFlags::HAS_TY_PLACEHOLDER } else { - TypeFlags::KEEP_IN_LOCAL_TCX + TypeFlags::KEEP_IN_LOCAL_TCX | + TypeFlags::HAS_RE_PLACEHOLDER | + TypeFlags::HAS_TY_PLACEHOLDER }; let gcx = tcx.global_tcx(); diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 9cdeb300393..3b84e7b54bd 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -74,7 +74,6 @@ impl FlagComputation { &ty::Uint(_) | &ty::Never | &ty::Str | - &ty::Placeholder(..) | &ty::Foreign(..) => { } @@ -120,6 +119,10 @@ impl FlagComputation { self.add_binder(bound_ty.index); } + &ty::Placeholder(..) => { + self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER); + } + &ty::Infer(infer) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right? self.add_flags(TypeFlags::HAS_TY_INFER); diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 9abc84e2a25..16de146cf4e 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -103,7 +103,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER) } fn has_placeholders(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_PLACEHOLDER) + self.has_type_flags(TypeFlags::HAS_RE_PLACEHOLDER | TypeFlags::HAS_TY_PLACEHOLDER) } fn needs_subst(&self) -> bool { self.has_type_flags(TypeFlags::NEEDS_SUBST) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 183aaadf6e6..b371f4532e5 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -467,6 +467,8 @@ bitflags! { /// if a global bound is safe to evaluate. const HAS_RE_LATE_BOUND = 1 << 13; + const HAS_TY_PLACEHOLDER = 1 << 14; + const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | TypeFlags::HAS_SELF.bits | TypeFlags::HAS_RE_EARLY_BOUND.bits; @@ -486,7 +488,8 @@ bitflags! { TypeFlags::HAS_TY_CLOSURE.bits | TypeFlags::HAS_FREE_LOCAL_NAMES.bits | TypeFlags::KEEP_IN_LOCAL_TCX.bits | - TypeFlags::HAS_RE_LATE_BOUND.bits; + TypeFlags::HAS_RE_LATE_BOUND.bits | + TypeFlags::HAS_TY_PLACEHOLDER.bits; } } From cdb96be11e178a82ac6b16f37ef2a9c2b7189d6b Mon Sep 17 00:00:00 2001 From: scalexm Date: Fri, 2 Nov 2018 19:46:30 +0100 Subject: [PATCH 0187/1984] Handle placeholder types in canonicalization --- src/librustc/ich/impls_ty.rs | 3 +- src/librustc/infer/canonical/canonicalizer.rs | 43 +++++++++++++++---- src/librustc/infer/canonical/mod.rs | 36 +++++++++++----- src/librustc/infer/mod.rs | 22 ++++++++++ src/librustc/infer/type_variable.rs | 2 +- 5 files changed, 85 insertions(+), 21 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 4b465c7ad54..e9fac5b9239 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -1099,12 +1099,13 @@ impl_stable_hash_for!(struct infer::canonical::CanonicalVarInfo { impl_stable_hash_for!(enum infer::canonical::CanonicalVarKind { Ty(k), + PlaceholderTy(placeholder), Region(ui), PlaceholderRegion(placeholder), }); impl_stable_hash_for!(enum infer::canonical::CanonicalTyVarKind { - General, + General(ui), Int, Float }); diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index a9c6c3b5085..7a9527573c7 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -339,11 +339,35 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match t.sty { - ty::Infer(ty::TyVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::General, t), + ty::Infer(ty::TyVar(vid)) => { + match self.infcx.unwrap().probe_ty_var(vid) { + // `t` could be a float / int variable: canonicalize that instead + Ok(t) => self.fold_ty(t), + + // `TyVar(vid)` is unresolved, track its universe index in the canonicalized + // result + Err(ui) => self.canonicalize_ty_var( + CanonicalVarInfo { + kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) + }, + t + ) + } + } - ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Int, t), + ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var( + CanonicalVarInfo { + kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) + }, + t + ), - ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Float, t), + ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var( + CanonicalVarInfo { + kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) + }, + t + ), ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) @@ -351,6 +375,13 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> bug!("encountered a fresh type during canonicalization") } + ty::Placeholder(placeholder) => self.canonicalize_ty_var( + CanonicalVarInfo { + kind: CanonicalVarKind::PlaceholderTy(placeholder) + }, + t + ), + ty::Bound(bound_ty) => { if bound_ty.index >= self.binder_index { bug!("escaping bound type during canonicalization") @@ -380,7 +411,6 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> | ty::Never | ty::Tuple(..) | ty::Projection(..) - | ty::Placeholder(..) | ty::UnnormalizedProjection(..) | ty::Foreign(..) | ty::Param(..) @@ -579,15 +609,12 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { /// if `ty_var` is bound to anything; if so, canonicalize /// *that*. Otherwise, create a new canonical variable for /// `ty_var`. - fn canonicalize_ty_var(&mut self, ty_kind: CanonicalTyVarKind, ty_var: Ty<'tcx>) -> Ty<'tcx> { + fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo, ty_var: Ty<'tcx>) -> Ty<'tcx> { let infcx = self.infcx.expect("encountered ty-var without infcx"); let bound_to = infcx.shallow_resolve(ty_var); if bound_to != ty_var { self.fold_ty(bound_to) } else { - let info = CanonicalVarInfo { - kind: CanonicalVarKind::Ty(ty_kind), - }; let var = self.canonical_var(info, ty_var.into()); self.tcx().mk_ty(ty::Bound(BoundTy::new(self.binder_index, var))) } diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index 41839d61d32..230f8958b33 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -122,6 +122,7 @@ impl CanonicalVarInfo { pub fn is_existential(&self) -> bool { match self.kind { CanonicalVarKind::Ty(_) => true, + CanonicalVarKind::PlaceholderTy(_) => false, CanonicalVarKind::Region(_) => true, CanonicalVarKind::PlaceholderRegion(..) => false, } @@ -136,6 +137,9 @@ pub enum CanonicalVarKind { /// Some kind of type inference variable. Ty(CanonicalTyVarKind), + /// A "placeholder" that represents "any type". + PlaceholderTy(ty::PlaceholderType), + /// Region variable `'?R`. Region(ty::UniverseIndex), @@ -148,12 +152,12 @@ pub enum CanonicalVarKind { impl CanonicalVarKind { pub fn universe(self) -> ty::UniverseIndex { match self { - // At present, we don't support higher-ranked - // quantification over types, so all type variables are in - // the root universe. - CanonicalVarKind::Ty(_) => ty::UniverseIndex::ROOT, + CanonicalVarKind::Ty(kind) => match kind { + CanonicalTyVarKind::General(ui) => ui, + CanonicalTyVarKind::Float | CanonicalTyVarKind::Int => ty::UniverseIndex::ROOT, + } - // Region variables can be created in sub-universes. + CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe, CanonicalVarKind::Region(ui) => ui, CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe, } @@ -168,7 +172,7 @@ impl CanonicalVarKind { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)] pub enum CanonicalTyVarKind { /// General type variable `?T` that can be unified with arbitrary types. - General, + General(ty::UniverseIndex), /// Integral type variable `?I` (that can only be unified with integral types). Int, @@ -358,8 +362,11 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { match cv_info.kind { CanonicalVarKind::Ty(ty_kind) => { let ty = match ty_kind { - CanonicalTyVarKind::General => { - self.next_ty_var(TypeVariableOrigin::MiscVariable(span)) + CanonicalTyVarKind::General(ui) => { + self.next_ty_var_in_universe( + TypeVariableOrigin::MiscVariable(span), + universe_map(ui) + ) } CanonicalTyVarKind::Int => self.tcx.mk_int_var(self.next_int_var_id()), @@ -369,6 +376,15 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { ty.into() } + CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, name }) => { + let universe_mapped = universe_map(universe); + let placeholder_mapped = ty::PlaceholderType { + universe: universe_mapped, + name, + }; + self.tcx.mk_ty(ty::Placeholder(placeholder_mapped)).into() + } + CanonicalVarKind::Region(ui) => self.next_region_var_in_universe( RegionVariableOrigin::MiscVariable(span), universe_map(ui), @@ -380,9 +396,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { universe: universe_mapped, name, }; - self.tcx - .mk_region(ty::RePlaceholder(placeholder_mapped)) - .into() + self.tcx.mk_region(ty::RePlaceholder(placeholder_mapped)).into() } } } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index dfe6aa160b3..6f041fdfb0a 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -972,6 +972,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.mk_var(self.next_ty_var_id(false, origin)) } + pub fn next_ty_var_in_universe( + &self, + origin: TypeVariableOrigin, + universe: ty::UniverseIndex + ) -> Ty<'tcx> { + let vid = self.type_variables + .borrow_mut() + .new_var(universe, false, origin); + self.tcx.mk_var(vid) + } + pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { self.tcx.mk_var(self.next_ty_var_id(true, origin)) } @@ -1227,6 +1238,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } + /// If `TyVar(vid)` resolves to a type, return that type. Else, return the + /// universe index of `TyVar(vid)`. + pub fn probe_ty_var(&self, vid: TyVid) -> Result, ty::UniverseIndex> { + use self::type_variable::TypeVariableValue; + + match self.type_variables.borrow_mut().probe(vid) { + TypeVariableValue::Known { value } => Ok(value), + TypeVariableValue::Unknown { universe } => Err(universe), + } + } + pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> { self.inlined_shallow_resolve(typ) } diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index bec19ba9099..5624961ea6e 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -72,7 +72,7 @@ pub type TypeVariableMap = FxHashMap; struct TypeVariableData { origin: TypeVariableOrigin, - diverging: bool + diverging: bool, } #[derive(Copy, Clone, Debug)] From 6bf17d249b1dc515eeafcdd04e30723120cb7899 Mon Sep 17 00:00:00 2001 From: scalexm Date: Sat, 3 Nov 2018 14:52:37 +0100 Subject: [PATCH 0188/1984] Instantiate all bound vars universally --- src/librustc/infer/higher_ranked/mod.rs | 43 ++++++++++++++++--------- src/librustc/infer/mod.rs | 6 ++-- src/librustc/traits/project.rs | 2 +- src/librustc/traits/select.rs | 10 +++--- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index ddf46b18ef7..5218aa36fac 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -53,7 +53,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { // First, we instantiate each bound region in the supertype with a // fresh placeholder region. let (b_prime, placeholder_map) = - self.infcx.replace_late_bound_regions_with_placeholders(b); + self.infcx.replace_bound_vars_with_placeholders(b); // Next, we instantiate each bound region in the subtype // with a fresh region variable. These region variables -- @@ -115,7 +115,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { // First, we instantiate each bound region in the matcher // with a placeholder region. let ((a_match, a_value), placeholder_map) = - self.infcx.replace_late_bound_regions_with_placeholders(a_pair); + self.infcx.replace_bound_vars_with_placeholders(a_pair); debug!("higher_ranked_match: a_match={:?}", a_match); debug!("higher_ranked_match: placeholder_map={:?}", placeholder_map); @@ -314,10 +314,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { region_vars } - /// Replace all regions bound by `binder` with placeholder regions and - /// return a map indicating which bound-region was replaced with what - /// placeholder region. This is the first step of checking subtyping - /// when higher-ranked things are involved. + /// Replace all regions (resp. types) bound by `binder` with placeholder + /// regions (resp. types) and return a map indicating which bound-region + /// was replaced with what placeholder region. This is the first step of + /// checking subtyping when higher-ranked things are involved. /// /// **Important:** you must call this function from within a snapshot. /// Moreover, before committing the snapshot, you must eventually call @@ -330,26 +330,37 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// the [rustc guide]. /// /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html - pub fn replace_late_bound_regions_with_placeholders( + pub fn replace_bound_vars_with_placeholders( &self, - binder: &ty::Binder, + binder: &ty::Binder ) -> (T, PlaceholderMap<'tcx>) where - T : TypeFoldable<'tcx>, + T: TypeFoldable<'tcx> { let next_universe = self.create_next_universe(); - let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| { + let fld_r = |br| { self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion { universe: next_universe, name: br, })) - }); + }; + + let fld_t = |bound_ty: ty::BoundTy| { + self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType { + universe: next_universe, + name: bound_ty.var, + })) + }; + + let (result, map) = self.tcx.replace_bound_vars(binder, fld_r, fld_t); - debug!("replace_late_bound_regions_with_placeholders(binder={:?}, result={:?}, map={:?})", - binder, - result, - map); + debug!( + "replace_bound_vars_with_placeholders(binder={:?}, result={:?}, map={:?})", + binder, + result, + map + ); (result, map) } @@ -530,7 +541,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// Pops the placeholder regions found in `placeholder_map` from the region /// inference context. Whenever you create placeholder regions via - /// `replace_late_bound_regions_with_placeholders`, they must be popped before you + /// `replace_bound_vars_with_placeholders`, they must be popped before you /// commit the enclosing snapshot (if you do not commit, e.g. within a /// probe or as a result of an error, then this is not necessary, as /// popping happens as part of the rollback). diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 6f041fdfb0a..a29c85bd2b1 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -227,7 +227,7 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { universe: Cell, } -/// A map returned by `replace_late_bound_regions_with_placeholders()` +/// A map returned by `replace_bound_vars_with_placeholders()` /// indicating the placeholder region that each late-bound region was /// replaced with. pub type PlaceholderMap<'tcx> = BTreeMap>; @@ -935,7 +935,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { b, }, placeholder_map, - ) = self.replace_late_bound_regions_with_placeholders(predicate); + ) = self.replace_bound_vars_with_placeholders(predicate); let cause_span = cause.span; let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; @@ -952,7 +952,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ) -> UnitResult<'tcx> { self.commit_if_ok(|snapshot| { let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) = - self.replace_late_bound_regions_with_placeholders(predicate); + self.replace_bound_vars_with_placeholders(predicate); let origin = SubregionOrigin::from_obligation_cause(cause, || { RelateRegionParamBound(cause.span) }); diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 0aabb7ad713..e7b5fc3d1ff 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -204,7 +204,7 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>( let infcx = selcx.infcx(); infcx.commit_if_ok(|snapshot| { let (placeholder_predicate, placeholder_map) = - infcx.replace_late_bound_regions_with_placeholders(&obligation.predicate); + infcx.replace_bound_vars_with_placeholders(&obligation.predicate); let skol_obligation = obligation.with(placeholder_predicate); let r = match project_and_unify_type(selcx, &skol_obligation) { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 6a91ad59d98..0cb071e3196 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1726,7 +1726,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let poly_trait_predicate = self.infcx() .resolve_type_vars_if_possible(&obligation.predicate); let (skol_trait_predicate, placeholder_map) = self.infcx() - .replace_late_bound_regions_with_placeholders(&poly_trait_predicate); + .replace_bound_vars_with_placeholders(&poly_trait_predicate); debug!( "match_projection_obligation_against_definition_bounds: \ skol_trait_predicate={:?} placeholder_map={:?}", @@ -2685,7 +2685,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.in_snapshot(|this, snapshot| { let (skol_ty, placeholder_map) = this.infcx() - .replace_late_bound_regions_with_placeholders(&ty); + .replace_bound_vars_with_placeholders(&ty); let Normalized { value: normalized_ty, mut obligations, @@ -2919,7 +2919,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let trait_obligations: Vec> = self.in_snapshot(|this, snapshot| { let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); let (trait_ref, placeholder_map) = this.infcx() - .replace_late_bound_regions_with_placeholders(&poly_trait_ref); + .replace_bound_vars_with_placeholders(&poly_trait_ref); let cause = obligation.derived_cause(ImplDerivedObligation); this.impl_or_trait_obligations( cause, @@ -3122,7 +3122,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.in_snapshot(|this, snapshot| { let (predicate, placeholder_map) = this.infcx() - .replace_late_bound_regions_with_placeholders(&obligation.predicate); + .replace_bound_vars_with_placeholders(&obligation.predicate); let trait_ref = predicate.trait_ref; let trait_def_id = trait_ref.def_id; let substs = trait_ref.substs; @@ -3585,7 +3585,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } let (skol_obligation, placeholder_map) = self.infcx() - .replace_late_bound_regions_with_placeholders(&obligation.predicate); + .replace_bound_vars_with_placeholders(&obligation.predicate); let skol_obligation_trait_ref = skol_obligation.trait_ref; let impl_substs = self.infcx From 95861b159072c404ad5ef2951d1f8c323a3878ca Mon Sep 17 00:00:00 2001 From: scalexm Date: Sat, 3 Nov 2018 15:15:33 +0100 Subject: [PATCH 0189/1984] Move `BoundTy` debruijn index to the `TyKind` enum variant --- src/librustc/ich/impls_ty.rs | 3 ++- src/librustc/infer/canonical/canonicalizer.rs | 8 ++++---- .../infer/canonical/query_response.rs | 8 ++++---- src/librustc/traits/select.rs | 6 +++--- src/librustc/traits/structural_impls.rs | 2 +- src/librustc/ty/error.rs | 2 +- src/librustc/ty/flags.rs | 4 ++-- src/librustc/ty/fold.rs | 19 ++++++++----------- src/librustc/ty/sty.rs | 12 +++++------- src/librustc/ty/subst.rs | 19 ++++++++++--------- src/librustc/util/ppaux.rs | 6 +++--- .../chalk_context/program_clauses.rs | 19 +++++++++++-------- src/librustc_traits/lowering/environment.rs | 2 +- src/librustc_traits/lowering/mod.rs | 3 ++- 14 files changed, 57 insertions(+), 56 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index e9fac5b9239..ad317a96590 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -684,7 +684,8 @@ for ty::TyKind<'gcx> Param(param_ty) => { param_ty.hash_stable(hcx, hasher); } - Bound(bound_ty) => { + Bound(debruijn, bound_ty) => { + debruijn.hash_stable(hcx, hasher); bound_ty.hash_stable(hcx, hasher); } ty::Placeholder(placeholder_ty) => { diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 7a9527573c7..ddb520775da 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -23,7 +23,7 @@ use infer::InferCtxt; use std::sync::atomic::Ordering; use ty::fold::{TypeFoldable, TypeFolder}; use ty::subst::Kind; -use ty::{self, BoundTy, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags}; +use ty::{self, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; @@ -382,8 +382,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> t ), - ty::Bound(bound_ty) => { - if bound_ty.index >= self.binder_index { + ty::Bound(debruijn, _) => { + if debruijn >= self.binder_index { bug!("escaping bound type during canonicalization") } else { t @@ -616,7 +616,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { self.fold_ty(bound_to) } else { let var = self.canonical_var(info, ty_var.into()); - self.tcx().mk_ty(ty::Bound(BoundTy::new(self.binder_index, var))) + self.tcx().mk_ty(ty::Bound(self.binder_index, var.into())) } } } diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 6f3d1026835..d32594ebdf3 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -435,21 +435,21 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { match result_value.unpack() { UnpackedKind::Type(result_value) => { // e.g., here `result_value` might be `?0` in the example above... - if let ty::Bound(b) = result_value.sty { + if let ty::Bound(debruijn, b) = result_value.sty { // ...in which case we would set `canonical_vars[0]` to `Some(?U)`. // We only allow a `ty::INNERMOST` index in substitutions. - assert_eq!(b.index, ty::INNERMOST); + assert_eq!(debruijn, ty::INNERMOST); opt_values[b.var] = Some(*original_value); } } UnpackedKind::Lifetime(result_value) => { // e.g., here `result_value` might be `'?1` in the example above... - if let &ty::RegionKind::ReLateBound(index, br) = result_value { + if let &ty::RegionKind::ReLateBound(debruijn, br) = result_value { // ... in which case we would set `canonical_vars[0]` to `Some('static)`. // We only allow a `ty::INNERMOST` index in substitutions. - assert_eq!(index, ty::INNERMOST); + assert_eq!(debruijn, ty::INNERMOST); opt_values[br.assert_bound_var()] = Some(*original_value); } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 0cb071e3196..0f59f478cb4 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2471,7 +2471,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::UnnormalizedProjection(..) | ty::Placeholder(..) - | ty::Bound(_) + | ty::Bound(..) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) => { @@ -2557,7 +2557,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::UnnormalizedProjection(..) | ty::Placeholder(..) - | ty::Bound(_) + | ty::Bound(..) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) => { @@ -2601,7 +2601,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { | ty::Param(..) | ty::Foreign(..) | ty::Projection(..) - | ty::Bound(_) + | ty::Bound(..) | ty::Infer(ty::TyVar(_)) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 3e417f10c44..36538ac0889 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -324,7 +324,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector { use syntax::symbol::Symbol; match t.sty { - ty::Bound(bound_ty) if bound_ty.index == self.binder_index => { + ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { self.types.insert( bound_ty.var.as_u32(), match bound_ty.kind { diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index e78759e3e79..90022a770c1 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -213,7 +213,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::Infer(ty::IntVar(_)) => "integral variable".into(), ty::Infer(ty::FloatVar(_)) => "floating-point variable".into(), ty::Placeholder(..) => "placeholder type".into(), - ty::Bound(_) | + ty::Bound(..) => "bound type".into(), ty::Infer(ty::FreshTy(_)) => "fresh type".into(), ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(), ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(), diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 3b84e7b54bd..1ea7e27c0dc 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -115,8 +115,8 @@ impl FlagComputation { self.add_substs(&substs.substs); } - &ty::Bound(bound_ty) => { - self.add_binder(bound_ty.index); + &ty::Bound(debruijn, _) => { + self.add_binder(debruijn); } &ty::Placeholder(..) => { diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 16de146cf4e..6f0e8d4f026 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -460,8 +460,8 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for BoundVarReplacer<'a, 'gcx, 'tcx> fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match t.sty { - ty::Bound(bound_ty) => { - if bound_ty.index == self.current_index { + ty::Bound(debruijn, bound_ty) => { + if debruijn == self.current_index { let fld_t = &mut self.fld_t; let ty = fld_t(bound_ty); ty::fold::shift_vars( @@ -526,7 +526,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { T: TypeFoldable<'tcx> { // identity for bound types - let fld_t = |bound_ty| self.mk_ty(ty::Bound(bound_ty)); + let fld_t = |bound_ty| self.mk_ty(ty::Bound(ty::INNERMOST, bound_ty)); self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t) } @@ -722,16 +722,13 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> { fn fold_ty(&mut self, ty: ty::Ty<'tcx>) -> ty::Ty<'tcx> { match ty.sty { - ty::Bound(bound_ty) => { - if self.amount == 0 || bound_ty.index < self.current_index { + ty::Bound(debruijn, bound_ty) => { + if self.amount == 0 || debruijn < self.current_index { ty } else { - let shifted = ty::BoundTy { - index: bound_ty.index.shifted_in(self.amount), - var: bound_ty.var, - kind: bound_ty.kind, - }; - self.tcx.mk_ty(ty::Bound(shifted)) + self.tcx.mk_ty( + ty::Bound(debruijn.shifted_in(self.amount), bound_ty) + ) } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index cd69d31a004..3056abba956 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -201,7 +201,7 @@ pub enum TyKind<'tcx> { Param(ParamTy), /// Bound type variable, used only when preparing a trait query. - Bound(BoundTy), + Bound(ty::DebruijnIndex, BoundTy), /// A placeholder type - universally quantified higher-ranked type. Placeholder(ty::PlaceholderType), @@ -1245,7 +1245,6 @@ newtype_index! { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct BoundTy { - pub index: DebruijnIndex, pub var: BoundVar, pub kind: BoundTyKind, } @@ -1256,13 +1255,12 @@ pub enum BoundTyKind { Param(InternedString), } -impl_stable_hash_for!(struct BoundTy { index, var, kind }); +impl_stable_hash_for!(struct BoundTy { var, kind }); impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) }); -impl BoundTy { - pub fn new(index: DebruijnIndex, var: BoundVar) -> Self { +impl From for BoundTy { + fn from(var: BoundVar) -> Self { BoundTy { - index, var, kind: BoundTyKind::Anon, } @@ -1957,7 +1955,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { ty::Infer(ty::TyVar(_)) => false, - ty::Bound(_) | + ty::Bound(..) | ty::Placeholder(..) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index b7f1731ba44..34252039898 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -190,11 +190,12 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { Substs::for_item(tcx, def_id, |param, _| { match param.kind { ty::GenericParamDefKind::Type { .. } => { - tcx.mk_ty(ty::Bound(ty::BoundTy { - index: ty::INNERMOST, - var: ty::BoundVar::from(param.index), - kind: ty::BoundTyKind::Param(param.name), - })).into() + tcx.mk_ty( + ty::Bound(ty::INNERMOST, ty::BoundTy { + var: ty::BoundVar::from(param.index), + kind: ty::BoundTyKind::Param(param.name), + }) + ).into() } ty::GenericParamDefKind::Lifetime => { @@ -584,18 +585,18 @@ impl CanonicalUserSubsts<'tcx> { self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { match kind.unpack() { UnpackedKind::Type(ty) => match ty.sty { - ty::Bound(b) => { + ty::Bound(debruijn, b) => { // We only allow a `ty::INNERMOST` index in substitutions. - assert_eq!(b.index, ty::INNERMOST); + assert_eq!(debruijn, ty::INNERMOST); cvar == b.var } _ => false, }, UnpackedKind::Lifetime(r) => match r { - ty::ReLateBound(index, br) => { + ty::ReLateBound(debruijn, br) => { // We only allow a `ty::INNERMOST` index in substitutions. - assert_eq!(*index, ty::INNERMOST); + assert_eq!(*debruijn, ty::INNERMOST); cvar == br.assert_bound_var() } _ => false, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 0c424b34415..eea3b54919d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1110,13 +1110,13 @@ define_print! { Infer(infer_ty) => write!(f, "{}", infer_ty), Error => write!(f, "[type error]"), Param(ref param_ty) => write!(f, "{}", param_ty), - Bound(bound_ty) => { + Bound(debruijn, bound_ty) => { match bound_ty.kind { ty::BoundTyKind::Anon => { - if bound_ty.index == ty::INNERMOST { + if debruijn == ty::INNERMOST { write!(f, "^{}", bound_ty.var.index()) } else { - write!(f, "^{}_{}", bound_ty.index.index(), bound_ty.var.index()) + write!(f, "^{}_{}", debruijn.index(), bound_ty.var.index()) } } diff --git a/src/librustc_traits/chalk_context/program_clauses.rs b/src/librustc_traits/chalk_context/program_clauses.rs index 5592d2a583c..b8670e5e914 100644 --- a/src/librustc_traits/chalk_context/program_clauses.rs +++ b/src/librustc_traits/chalk_context/program_clauses.rs @@ -59,7 +59,8 @@ fn assemble_clauses_from_assoc_ty_values<'tcx>( fn program_clauses_for_raw_ptr<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> { let ty = ty::Bound( - ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0)) + ty::INNERMOST, + ty::BoundVar::from_u32(0).into() ); let ty = tcx.mk_ty(ty); @@ -88,9 +89,9 @@ fn program_clauses_for_fn_ptr<'tcx>( ) -> Clauses<'tcx> { let inputs_and_output = tcx.mk_type_list( (0..arity_and_output).into_iter() + .map(|i| ty::BoundVar::from(i)) // DebruijnIndex(1) because we are going to inject these in a `PolyFnSig` - .map(|i| ty::BoundTy::new(ty::DebruijnIndex::from(1usize), ty::BoundVar::from(i))) - .map(|t| tcx.mk_ty(ty::Bound(t))) + .map(|var| tcx.mk_ty(ty::Bound(ty::DebruijnIndex::from(1usize), var.into()))) ); let fn_sig = ty::Binder::bind(ty::FnSig { @@ -115,7 +116,8 @@ fn program_clauses_for_fn_ptr<'tcx>( fn program_clauses_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> { let ty = ty::Bound( - ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0)) + ty::INNERMOST, + ty::BoundVar::from_u32(0).into() ); let ty = tcx.mk_ty(ty); @@ -151,7 +153,8 @@ fn program_clauses_for_array<'tcx>( length: &'tcx ty::Const<'tcx> ) -> Clauses<'tcx> { let ty = ty::Bound( - ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0)) + ty::INNERMOST, + ty::BoundVar::from_u32(0).into() ); let ty = tcx.mk_ty(ty); @@ -188,8 +191,8 @@ fn program_clauses_for_tuple<'tcx>( ) -> Clauses<'tcx> { let type_list = tcx.mk_type_list( (0..arity).into_iter() - .map(|i| ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from(i))) - .map(|t| tcx.mk_ty(ty::Bound(t))) + .map(|i| ty::BoundVar::from(i)) + .map(|var| tcx.mk_ty(ty::Bound(ty::INNERMOST, var.into()))) ); let tuple_ty = tcx.mk_ty(ty::Tuple(type_list)); @@ -233,7 +236,7 @@ fn program_clauses_for_ref<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0)) ); let ty = tcx.mk_ty( - ty::Bound(ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(1))) + ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(1).into()) ); let ref_ty = tcx.mk_ref(region, ty::TypeAndMut { diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs index c3573f47ceb..519b0ac6105 100644 --- a/src/librustc_traits/lowering/environment.rs +++ b/src/librustc_traits/lowering/environment.rs @@ -55,7 +55,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> { ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0)) ); let ty = self.tcx.mk_ty( - ty::Bound(ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(1))) + ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(1).into()) ); let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index cf1bc04dd4e..2d8e5b48aac 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -515,7 +515,8 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>( .unwrap_or(0); // Add a new type param after the existing ones (`U` in the comment above). let ty_var = ty::Bound( - ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(offset + 1)) + ty::INNERMOST, + ty::BoundVar::from_u32(offset + 1).into() ); // `ProjectionEq(>::AssocType = U)` From 5b2baa8336ab85f958ac6a8e78e71b490a43e474 Mon Sep 17 00:00:00 2001 From: scalexm Date: Sat, 3 Nov 2018 16:08:50 +0100 Subject: [PATCH 0190/1984] Implement some instantiate / canonical routines --- src/librustc_traits/chalk_context/mod.rs | 165 ++++++++++++++++------- 1 file changed, 113 insertions(+), 52 deletions(-) diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs index 0fd9f607a54..14d4be2b178 100644 --- a/src/librustc_traits/chalk_context/mod.rs +++ b/src/librustc_traits/chalk_context/mod.rs @@ -11,7 +11,7 @@ mod program_clauses; use chalk_engine::fallible::Fallible as ChalkEngineFallible; -use chalk_engine::{context, hh::HhGoal, DelayedLiteral, ExClause}; +use chalk_engine::{context, hh::HhGoal, DelayedLiteral, Literal, ExClause}; use rustc::infer::canonical::{ Canonical, CanonicalVarValues, OriginalQueryValues, QueryRegionConstraint, QueryResponse, }; @@ -28,7 +28,7 @@ use rustc::traits::{ InEnvironment, }; use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use rustc::ty::subst::Kind; +use rustc::ty::subst::{Kind, UnpackedKind}; use rustc::ty::{self, TyCtxt}; use std::fmt::{self, Debug}; @@ -44,7 +44,7 @@ crate struct ChalkArenas<'gcx> { #[derive(Copy, Clone)] crate struct ChalkContext<'cx, 'gcx: 'cx> { _arenas: ChalkArenas<'gcx>, - _tcx: TyCtxt<'cx, 'gcx, 'gcx>, + tcx: TyCtxt<'cx, 'gcx, 'gcx>, } #[derive(Copy, Clone)] @@ -68,7 +68,7 @@ BraceStructTypeFoldableImpl! { } impl context::Context for ChalkArenas<'tcx> { - type CanonicalExClause = Canonical<'tcx, ExClause>; + type CanonicalExClause = Canonical<'tcx, ChalkExClause<'tcx>>; type CanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>; @@ -147,19 +147,29 @@ impl context::ContextOps> for ChalkContext<'cx, 'gcx> { /// - the environment and goal found by substitution `S` into `arg` fn instantiate_ucanonical_goal( &self, - _arg: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>, - _op: impl context::WithInstantiatedUCanonicalGoal, Output = R>, + arg: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>, + op: impl context::WithInstantiatedUCanonicalGoal, Output = R>, ) -> R { - unimplemented!() + self.tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, arg, |ref infcx, arg, subst| { + let chalk_infcx = &mut ChalkInferenceContext { + infcx, + }; + op.with(chalk_infcx, subst, arg.environment, arg.goal) + }) } fn instantiate_ex_clause( &self, _num_universes: usize, - _canonical_ex_clause: &Canonical<'gcx, ChalkExClause<'gcx>>, - _op: impl context::WithInstantiatedExClause, Output = R>, + arg: &Canonical<'gcx, ChalkExClause<'gcx>>, + op: impl context::WithInstantiatedExClause, Output = R>, ) -> R { - unimplemented!() + self.tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, &arg.upcast(), |ref infcx, arg, _| { + let chalk_infcx = &mut ChalkInferenceContext { + infcx, + }; + op.with(chalk_infcx,arg) + }) } /// True if this solution has no region constraints. @@ -186,14 +196,33 @@ impl context::ContextOps> for ChalkContext<'cx, 'gcx> { } fn is_trivial_substitution( - _u_canon: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>, - _canonical_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>, + u_canon: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>, + canonical_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>, ) -> bool { - unimplemented!() - } - - fn num_universes(_: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>) -> usize { - 0 // FIXME + let subst = &canonical_subst.value.subst; + assert_eq!(u_canon.variables.len(), subst.var_values.len()); + subst.var_values + .iter_enumerated() + .all(|(cvar, kind)| match kind.unpack() { + UnpackedKind::Lifetime(r) => match r { + &ty::ReLateBound(debruijn, br) => { + debug_assert_eq!(debruijn, ty::INNERMOST); + cvar == br.assert_bound_var() + } + _ => false, + }, + UnpackedKind::Type(ty) => match ty.sty { + ty::Bound(debruijn, bound_ty) => { + debug_assert_eq!(debruijn, ty::INNERMOST); + cvar == bound_ty.var + } + _ => false, + }, + }) + } + + fn num_universes(canon: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>) -> usize { + canon.max_universe.index() + 1 } /// Convert a goal G *from* the canonical universes *into* our @@ -214,39 +243,6 @@ impl context::ContextOps> for ChalkContext<'cx, 'gcx> { } } -//impl context::UCanonicalGoalInEnvironment> -// for Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> -//{ -// fn canonical(&self) -> &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> { -// self -// } -// -// fn is_trivial_substitution( -// &self, -// canonical_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>, -// ) -> bool { -// let subst = &canonical_subst.value.subst; -// assert_eq!(self.canonical.variables.len(), subst.var_values.len()); -// subst -// .var_values -// .iter_enumerated() -// .all(|(cvar, kind)| match kind.unpack() { -// Kind::Lifetime(r) => match r { -// ty::ReCanonical(cvar1) => cvar == cvar1, -// _ => false, -// }, -// Kind::Type(ty) => match ty.sty { -// ty::Infer(ty::InferTy::CanonicalTy(cvar1)) => cvar == cvar1, -// _ => false, -// }, -// }) -// } -// -// fn num_universes(&self) -> usize { -// 0 // FIXME -// } -//} - impl context::InferenceTable, ChalkArenas<'tcx>> for ChalkInferenceContext<'cx, 'gcx, 'tcx> { @@ -338,9 +334,9 @@ impl context::UnificationOps, ChalkArenas<'tcx>> fn instantiate_binders_universally( &mut self, - _arg: &ty::Binder>, + arg: &ty::Binder>, ) -> Goal<'tcx> { - panic!("FIXME -- universal instantiation needs sgrif's branch") + self.infcx.replace_bound_vars_with_placeholders(arg).0 } fn instantiate_binders_existentially( @@ -491,3 +487,68 @@ BraceStructLiftImpl! { subst, constraints } } + +trait Upcast<'tcx, 'gcx: 'tcx>: 'gcx { + type Upcasted: 'tcx; + + fn upcast(&self) -> Self::Upcasted; +} + +impl<'tcx, 'gcx: 'tcx> Upcast<'tcx, 'gcx> for DelayedLiteral> { + type Upcasted = DelayedLiteral>; + + fn upcast(&self) -> Self::Upcasted { + match self { + &DelayedLiteral::CannotProve(..) => DelayedLiteral::CannotProve(()), + &DelayedLiteral::Negative(index) => DelayedLiteral::Negative(index), + DelayedLiteral::Positive(index, subst) => DelayedLiteral::Positive( + *index, + subst.clone() + ), + } + } +} + +impl<'tcx, 'gcx: 'tcx> Upcast<'tcx, 'gcx> for Literal> { + type Upcasted = Literal>; + + fn upcast(&self) -> Self::Upcasted { + match self { + &Literal::Negative(goal) => Literal::Negative(goal), + &Literal::Positive(goal) => Literal::Positive(goal), + } + } +} + +impl<'tcx, 'gcx: 'tcx> Upcast<'tcx, 'gcx> for ExClause> { + type Upcasted = ExClause>; + + fn upcast(&self) -> Self::Upcasted { + ExClause { + subst: self.subst.clone(), + delayed_literals: self.delayed_literals + .iter() + .map(|l| l.upcast()) + .collect(), + constraints: self.constraints.clone(), + subgoals: self.subgoals + .iter() + .map(|g| g.upcast()) + .collect(), + } + } +} + +impl<'tcx, 'gcx: 'tcx, T> Upcast<'tcx, 'gcx> for Canonical<'gcx, T> + where T: Upcast<'tcx, 'gcx> +{ + type Upcasted = Canonical<'tcx, T::Upcasted>; + + fn upcast(&self) -> Self::Upcasted { + Canonical { + max_universe: self.max_universe, + value: self.value.upcast(), + variables: self.variables, + } + } +} From c0f98e83906453e0f563a6f925f5c6e14f93a0ba Mon Sep 17 00:00:00 2001 From: scalexm Date: Mon, 5 Nov 2018 18:08:47 +0100 Subject: [PATCH 0191/1984] Fix `ChalkInferenceContext::into_hh_goal` --- src/librustc_traits/chalk_context/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs index 14d4be2b178..25a6af284b5 100644 --- a/src/librustc_traits/chalk_context/mod.rs +++ b/src/librustc_traits/chalk_context/mod.rs @@ -256,7 +256,10 @@ impl context::InferenceTable, ChalkArenas<'tcx>> fn into_hh_goal(&mut self, goal: Goal<'tcx>) -> ChalkHhGoal<'tcx> { match *goal { - GoalKind::Implies(..) => panic!("FIXME rust-lang-nursery/chalk#94"), + GoalKind::Implies(hypotheses, goal) => HhGoal::Implies( + hypotheses.iter().cloned().collect(), + goal + ), GoalKind::And(left, right) => HhGoal::And(left, right), GoalKind::Not(subgoal) => HhGoal::Not(subgoal), GoalKind::DomainGoal(d) => HhGoal::DomainGoal(d), From 4478dced472dec4f516cc4ef553a1476e40c09b8 Mon Sep 17 00:00:00 2001 From: scalexm Date: Wed, 14 Nov 2018 12:50:26 +0100 Subject: [PATCH 0192/1984] Fix NLL ui test --- src/test/ui/nll/user-annotations/dump-fn-method.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/nll/user-annotations/dump-fn-method.stderr b/src/test/ui/nll/user-annotations/dump-fn-method.stderr index 359423d0cfb..c963625c961 100644 --- a/src/test/ui/nll/user-annotations/dump-fn-method.stderr +++ b/src/test/ui/nll/user-annotations/dump-fn-method.stderr @@ -4,7 +4,7 @@ error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubs LL | let x = foo::; //~ ERROR [u32] | ^^^^^^^^^^ -error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } } +error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }, CanonicalVarInfo { kind: Ty(General(U0)) }], value: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } } --> $DIR/dump-fn-method.rs:42:13 | LL | let x = <_ as Bazoom>::method::<_>; //~ ERROR [^0, u32, ^1] @@ -16,7 +16,7 @@ error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubs LL | let x = >::method::; //~ ERROR [u8, u16, u32] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } } +error: user substs: Canonical { max_universe: U1, variables: [CanonicalVarInfo { kind: Ty(General(U1)) }, CanonicalVarInfo { kind: Ty(General(U1)) }], value: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } } --> $DIR/dump-fn-method.rs:54:5 | LL | y.method::(44, 66); //~ ERROR [^0, ^1, u32] From 93520d2ad145b791b1b1a6c71cdea65b1943ffb6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 6 Nov 2018 01:40:12 +0100 Subject: [PATCH 0193/1984] Add source file sidebar --- src/librustdoc/html/layout.rs | 8 +- src/librustdoc/html/render.rs | 85 ++++++++++- src/librustdoc/html/static/main.js | 66 ++------- src/librustdoc/html/static/rustdoc.css | 63 ++++++++- src/librustdoc/html/static/source-script.js | 147 ++++++++++++++++++++ src/librustdoc/html/static/storage.js | 40 ++++++ src/librustdoc/html/static/themes/dark.css | 19 +++ src/librustdoc/html/static/themes/light.css | 19 +++ 8 files changed, 384 insertions(+), 63 deletions(-) create mode 100644 src/librustdoc/html/static/source-script.js diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 6868c7707ad..fd6bd83e29f 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -33,7 +33,7 @@ pub struct Page<'a> { pub fn render( dst: &mut dyn io::Write, layout: &Layout, page: &Page, sidebar: &S, t: &T, - css_file_extension: bool, themes: &[PathBuf]) + css_file_extension: bool, themes: &[PathBuf], extra_scripts: &[&str]) -> io::Result<()> { write!(dst, @@ -149,6 +149,7 @@ pub fn render( \ \ \ + {extra_scripts}\ \ \ ", @@ -192,6 +193,11 @@ pub fn render( page.resource_suffix)) .collect::(), suffix=page.resource_suffix, + extra_scripts=extra_scripts.iter().map(|e| { + format!("", + root_path=page.root_path, + extra_script=e) + }).collect::(), ) } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index b46efb20d8f..a106a773571 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -859,6 +859,9 @@ themePicker.onblur = handleThemeButtonsBlur; write_minify(cx.dst.join(&format!("settings{}.js", cx.shared.resource_suffix)), static_files::SETTINGS_JS, options.enable_minification)?; + write_minify(cx.dst.join(&format!("source-script{}.js", cx.shared.resource_suffix)), + include_str!("static/source-script.js"), + options.enable_minification)?; { let mut data = format!("var resourcesSuffix = \"{}\";\n", @@ -969,10 +972,82 @@ themePicker.onblur = handleThemeButtonsBlur; } } + use std::ffi::OsString; + + #[derive(Debug)] + struct Hierarchy { + elem: OsString, + children: FxHashMap, + elems: FxHashSet, + } + + impl Hierarchy { + fn new(elem: OsString) -> Hierarchy { + Hierarchy { + elem, + children: FxHashMap::default(), + elems: FxHashSet::default(), + } + } + + fn to_string(&self) -> String { + let mut subs: Vec<&Hierarchy> = self.children.iter().map(|(_, v)| v).collect(); + subs.sort_unstable_by(|a, b| a.elem.cmp(&b.elem)); + let mut files = self.elems.iter() + .map(|s| format!("\"{}\"", + s.to_str() + .expect("invalid osstring conversion"))) + .collect::>(); + files.sort_unstable_by(|a, b| a.cmp(b)); + // FIXME(imperio): we could avoid to generate "dirs" and "files" if they're empty. + format!("{{\"name\":\"{name}\",\"dirs\":[{subs}],\"files\":[{files}]}}", + name=self.elem.to_str().expect("invalid osstring conversion"), + subs=subs.iter().map(|s| s.to_string()).collect::>().join(","), + files=files.join(",")) + } + } + + use std::path::Component; + + let mut hierarchy = Hierarchy::new(OsString::new()); + for source in cx.shared.local_sources.iter() + .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root) + .ok()) { + let mut h = &mut hierarchy; + let mut elems = source.components() + .filter_map(|s| { + match s { + Component::Normal(s) => Some(s.to_owned()), + _ => None, + } + }) + .peekable(); + loop { + let cur_elem = elems.next().expect("empty file path"); + if elems.peek().is_none() { + h.elems.insert(cur_elem); + break; + } else { + let e = cur_elem.clone(); + h.children.entry(cur_elem.clone()).or_insert_with(|| Hierarchy::new(e)); + h = h.children.get_mut(&cur_elem).expect("not found child"); + } + } + } + + let dst = cx.dst.join("source-files.js"); + let (mut all_sources, _krates) = try_err!(collect(&dst, &krate.name, "sourcesIndex"), &dst); + all_sources.push(format!("sourcesIndex['{}'] = {};", &krate.name, hierarchy.to_string())); + all_sources.sort(); + let mut w = try_err!(File::create(&dst), &dst); + try_err!(writeln!(&mut w, "var N = null;var sourcesIndex = {{}};\n{}", all_sources.join("\n")), + &dst); + // Update the search index let dst = cx.dst.join("search-index.js"); let (mut all_indexes, mut krates) = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst); all_indexes.push(search_index); + // Sort the indexes by crate so the file will be generated identically even // with rustdoc running in parallel. all_indexes.sort(); @@ -1020,7 +1095,7 @@ themePicker.onblur = handleThemeButtonsBlur; try_err!(layout::render(&mut w, &cx.shared.layout, &page, &(""), &content, cx.shared.css_file_extension.is_some(), - &cx.shared.themes), &dst); + &cx.shared.themes, &[]), &dst); try_err!(w.flush(), &dst); } } @@ -1292,7 +1367,7 @@ impl<'a> SourceCollector<'a> { layout::render(&mut w, &self.scx.layout, &page, &(""), &Source(contents), self.scx.css_file_extension.is_some(), - &self.scx.themes)?; + &self.scx.themes, &["source-files.js", "source-script.js"])?; w.flush()?; self.scx.local_sources.insert(p.clone(), href); Ok(()) @@ -1890,7 +1965,7 @@ impl Context { try_err!(layout::render(&mut w, &self.shared.layout, &page, &sidebar, &all, self.shared.css_file_extension.is_some(), - &self.shared.themes), + &self.shared.themes, &[]), &final_file); // Generating settings page. @@ -1910,7 +1985,7 @@ impl Context { try_err!(layout::render(&mut w, &layout, &page, &sidebar, &settings, self.shared.css_file_extension.is_some(), - &themes), + &themes, &[]), &settings_file); Ok(()) @@ -1968,7 +2043,7 @@ impl Context { &Sidebar{ cx: self, item: it }, &Item{ cx: self, item: it }, self.shared.css_file_extension.is_some(), - &self.shared.themes)?; + &self.shared.themes, &[])?; } else { let mut url = self.root_path(); if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) { diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 55415e973c5..781f99cd693 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -13,6 +13,19 @@ /*jslint browser: true, es5: true */ /*globals $: true, rootPath: true */ +if (!String.prototype.startsWith) { + String.prototype.startsWith = function(searchString, position) { + position = position || 0; + return this.indexOf(searchString, position) === position; + }; +} +if (!String.prototype.endsWith) { + String.prototype.endsWith = function(suffix, length) { + var l = length || this.length; + return this.indexOf(suffix, l - suffix.length) !== -1; + }; +} + (function() { "use strict"; @@ -57,19 +70,6 @@ var titleBeforeSearch = document.title; - if (!String.prototype.startsWith) { - String.prototype.startsWith = function(searchString, position) { - position = position || 0; - return this.indexOf(searchString, position) === position; - }; - } - if (!String.prototype.endsWith) { - String.prototype.endsWith = function(suffix, length) { - var l = length || this.length; - return this.indexOf(suffix, l - suffix.length) !== -1; - }; - } - function getPageId() { var id = document.location.href.split('#')[1]; if (id) { @@ -78,46 +78,6 @@ return null; } - function hasClass(elem, className) { - if (elem && className && elem.className) { - var elemClass = elem.className; - var start = elemClass.indexOf(className); - if (start === -1) { - return false; - } else if (elemClass.length === className.length) { - return true; - } else { - if (start > 0 && elemClass[start - 1] !== ' ') { - return false; - } - var end = start + className.length; - return !(end < elemClass.length && elemClass[end] !== ' '); - } - } - return false; - } - - function addClass(elem, className) { - if (elem && className && !hasClass(elem, className)) { - if (elem.className && elem.className.length > 0) { - elem.className += ' ' + className; - } else { - elem.className = className; - } - } - } - - function removeClass(elem, className) { - if (elem && className && elem.className) { - elem.className = (" " + elem.className + " ").replace(" " + className + " ", " ") - .trim(); - } - } - - function isHidden(elem) { - return (elem.offsetParent === null) - } - function showSidebar() { var elems = document.getElementsByClassName("sidebar-elems")[0]; if (elems) { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index b2473dd9b23..5dbba3ebab5 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -113,7 +113,8 @@ h3.impl, h3.method, h3.type { h1, h2, h3, h4, .sidebar, a.source, .search-input, .content table :not(code)>a, -.collapse-toggle, div.item-list .out-of-band { +.collapse-toggle, div.item-list .out-of-band, +#source-sidebar, #sidebar-toggle { font-family: "Fira Sans", sans-serif; } @@ -668,9 +669,9 @@ a { padding-right: 10px; } .content .search-results td:first-child a:after { - clear: both; - content: ""; - display: block; + clear: both; + content: ""; + display: block; } .content .search-results td:first-child a span { float: left; @@ -1459,3 +1460,57 @@ kbd { .non-exhaustive { margin-bottom: 1em; } + +#sidebar-toggle { + position: fixed; + top: 30px; + right: 300px; + z-index: 10; + padding: 3px; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; + cursor: pointer; + font-weight: bold; + transition: right 1s; + font-size: 1.2em; +} +#source-sidebar { + position: fixed; + top: 0; + bottom: 0; + right: 0; + width: 300px; + z-index: 1; + overflow: auto; + transition: right 1s; +} +#source-sidebar > .title { + font-size: 1.5em; + text-align: center; + border-bottom: 1px solid; + margin-bottom: 6px; +} + +div.children { + padding-left: 27px; + display: none; +} +div.files > a { + display: block; + padding: 0 3px; +} +div.files > a:hover, div.name:hover { + background-color: #a14b4b; +} +div.name.expand + .children { + display: block; +} +div.name::before { + content: "\25B6"; + display: inline-block; + padding-right: 4px; + font-size: 0.7em; +} +div.name.expand::before { + transform: rotate(90deg); +} diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js new file mode 100644 index 00000000000..59b82361c09 --- /dev/null +++ b/src/librustdoc/html/static/source-script.js @@ -0,0 +1,147 @@ +/*! + * Copyright 2018 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. + */ + +function getCurrentFilePath() { + var parts = window.location.pathname.split("/"); + var rootPathParts = window.rootPath.split("/"); + + for (var i = 0; i < rootPathParts.length; ++i) { + if (rootPathParts[i] === "..") { + parts.pop(); + } + } + var file = window.location.pathname.substring(parts.join("/").length); + if (file.startsWith("/")) { + file = file.substring(1); + } + return file.substring(0, file.length - 5); +} + +function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) { + var name = document.createElement("div"); + name.className = "name"; + + fullPath += elem["name"] + "/"; + + name.onclick = function() { + if (hasClass(this, "expand")) { + removeClass(this, "expand"); + } else { + addClass(this, "expand"); + } + }; + name.innerText = elem["name"]; + + var children = document.createElement("div"); + children.className = "children"; + var folders = document.createElement("div"); + folders.className = "folders"; + for (var i = 0; i < elem.dirs.length; ++i) { + if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile, + hasFoundFile) === true) { + addClass(name, "expand"); + hasFoundFile = true; + } + } + children.appendChild(folders); + + var files = document.createElement("div"); + files.className = "files"; + for (i = 0; i < elem.files.length; ++i) { + var file = document.createElement("a"); + file.innerText = elem.files[i]; + file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html"; + if (hasFoundFile === false && + currentFile === fullPath + elem.files[i]) { + file.className = "selected"; + addClass(name, "expand"); + hasFoundFile = true; + } + files.appendChild(file); + } + search.fullPath = fullPath; + children.appendChild(files); + parent.appendChild(name); + parent.appendChild(children); + return hasFoundFile === true && search.currentFile !== null; +} + +function toggleSidebar() { + var sidebar = document.getElementById("source-sidebar"); + var child = this.children[0].children[0]; + if (child.innerText === "<") { + sidebar.style.right = ""; + this.style.right = ""; + child.innerText = ">"; + updateLocalStorage("rustdoc-source-sidebar-hidden", "false"); + } else { + sidebar.style.right = "-300px"; + this.style.right = "0"; + child.innerText = "<"; + updateLocalStorage("rustdoc-source-sidebar-hidden", "true"); + } +} + +function createSidebarToggle() { + var sidebarToggle = document.createElement("div"); + sidebarToggle.id = "sidebar-toggle"; + sidebarToggle.onclick = toggleSidebar; + + var inner1 = document.createElement("div"); + inner1.style.position = "relative"; + + var inner2 = document.createElement("div"); + inner2.style.marginTop = "-2px"; + if (getCurrentValue("rustdoc-source-sidebar-hidden") === "true") { + inner2.innerText = "<"; + sidebarToggle.style.right = "0"; + } else { + inner2.innerText = ">"; + } + + inner1.appendChild(inner2); + sidebarToggle.appendChild(inner1); + return sidebarToggle; +} + +function createSourceSidebar() { + if (window.rootPath.endsWith("/") === false) { + window.rootPath += "/"; + } + var main = document.getElementById("main"); + + var sidebarToggle = createSidebarToggle(); + main.insertBefore(sidebarToggle, main.firstChild); + + var sidebar = document.createElement("div"); + sidebar.id = "source-sidebar"; + if (getCurrentValue("rustdoc-source-sidebar-hidden") === "true") { + sidebar.style.right = "-300px"; + } + + var currentFile = getCurrentFilePath(); + var hasFoundFile = false; + + var title = document.createElement("div"); + title.className = "title"; + title.innerText = "Files"; + sidebar.appendChild(title); + Object.keys(sourcesIndex).forEach(function(key) { + sourcesIndex[key].name = key; + hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "", + currentFile, hasFoundFile); + }); + + main.insertBefore(sidebar, main.firstChild); +} + +createSourceSidebar(); diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index 5f7a8c75d3c..150001a7514 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -15,6 +15,46 @@ var mainTheme = document.getElementById("mainThemeStyle"); var savedHref = []; +function hasClass(elem, className) { + if (elem && className && elem.className) { + var elemClass = elem.className; + var start = elemClass.indexOf(className); + if (start === -1) { + return false; + } else if (elemClass.length === className.length) { + return true; + } else { + if (start > 0 && elemClass[start - 1] !== ' ') { + return false; + } + var end = start + className.length; + return !(end < elemClass.length && elemClass[end] !== ' '); + } + } + return false; +} + +function addClass(elem, className) { + if (elem && className && !hasClass(elem, className)) { + if (elem.className && elem.className.length > 0) { + elem.className += ' ' + className; + } else { + elem.className = className; + } + } +} + +function removeClass(elem, className) { + if (elem && className && elem.className) { + elem.className = (" " + elem.className + " ").replace(" " + className + " ", " ") + .trim(); + } +} + +function isHidden(elem) { + return (elem.offsetParent === null) +} + function onEach(arr, func, reversed) { if (arr && arr.length > 0 && func) { if (reversed !== true) { diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 4a8950b236c..acf9a8cca64 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -416,3 +416,22 @@ kbd { .impl-items code { background-color: rgba(0, 0, 0, 0); } + +#sidebar-toggle { + background-color: #565656; +} +#sidebar-toggle:hover { + background-color: #676767; +} +#source-sidebar { + background-color: #565656; +} +#source-sidebar > .title { + border-bottom-color: #ccc; +} +div.files > a:hover, div.name:hover { + background-color: #444; +} +div.files > .selected { + background-color: #333; +} diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index b3b0b6b2ea9..d98f1718a6a 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -410,3 +410,22 @@ kbd { .impl-items code { background-color: rgba(0, 0, 0, 0); } + +#sidebar-toggle { + background-color: #F1F1F1; +} +#sidebar-toggle:hover { + background-color: #E0E0E0; +} +#source-sidebar { + background-color: #F1F1F1; +} +#source-sidebar > .title { + border-bottom-color: #ccc; +} +div.files > a:hover, div.name:hover { + background-color: #E0E0E0; +} +div.files > .selected { + background-color: #fff; +} From e87f8cc49b56ea2b8f01281a0b2baf20e12a319d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 16 Nov 2018 11:36:40 +0100 Subject: [PATCH 0194/1984] Source sidebar improvements --- src/librustdoc/html/layout.rs | 5 +- src/librustdoc/html/render.rs | 84 +++++++++++---------- src/librustdoc/html/static/rustdoc.css | 27 +++++-- src/librustdoc/html/static/source-script.js | 24 +++--- src/librustdoc/html/static_files.rs | 6 ++ 5 files changed, 86 insertions(+), 60 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index fd6bd83e29f..287e5a31888 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -194,9 +194,10 @@ pub fn render( .collect::(), suffix=page.resource_suffix, extra_scripts=extra_scripts.iter().map(|e| { - format!("", + format!("", root_path=page.root_path, - extra_script=e) + extra_script=e, + suffix=page.resource_suffix) }).collect::(), ) } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index a106a773571..7b020415af1 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -859,9 +859,11 @@ themePicker.onblur = handleThemeButtonsBlur; write_minify(cx.dst.join(&format!("settings{}.js", cx.shared.resource_suffix)), static_files::SETTINGS_JS, options.enable_minification)?; - write_minify(cx.dst.join(&format!("source-script{}.js", cx.shared.resource_suffix)), - include_str!("static/source-script.js"), - options.enable_minification)?; + if cx.shared.include_sources { + write_minify(cx.dst.join(&format!("source-script{}.js", cx.shared.resource_suffix)), + static_files::sidebar::SOURCE_SCRIPT, + options.enable_minification)?; + } { let mut data = format!("var resourcesSuffix = \"{}\";\n", @@ -990,8 +992,8 @@ themePicker.onblur = handleThemeButtonsBlur; } } - fn to_string(&self) -> String { - let mut subs: Vec<&Hierarchy> = self.children.iter().map(|(_, v)| v).collect(); + fn to_json_string(&self) -> String { + let mut subs: Vec<&Hierarchy> = self.children.values().collect(); subs.sort_unstable_by(|a, b| a.elem.cmp(&b.elem)); let mut files = self.elems.iter() .map(|s| format!("\"{}\"", @@ -1002,46 +1004,52 @@ themePicker.onblur = handleThemeButtonsBlur; // FIXME(imperio): we could avoid to generate "dirs" and "files" if they're empty. format!("{{\"name\":\"{name}\",\"dirs\":[{subs}],\"files\":[{files}]}}", name=self.elem.to_str().expect("invalid osstring conversion"), - subs=subs.iter().map(|s| s.to_string()).collect::>().join(","), + subs=subs.iter().map(|s| s.to_json_string()).collect::>().join(","), files=files.join(",")) } } - use std::path::Component; + if cx.shared.include_sources { + use std::path::Component; - let mut hierarchy = Hierarchy::new(OsString::new()); - for source in cx.shared.local_sources.iter() - .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root) - .ok()) { - let mut h = &mut hierarchy; - let mut elems = source.components() - .filter_map(|s| { - match s { - Component::Normal(s) => Some(s.to_owned()), - _ => None, - } - }) - .peekable(); - loop { - let cur_elem = elems.next().expect("empty file path"); - if elems.peek().is_none() { - h.elems.insert(cur_elem); - break; - } else { - let e = cur_elem.clone(); - h.children.entry(cur_elem.clone()).or_insert_with(|| Hierarchy::new(e)); - h = h.children.get_mut(&cur_elem).expect("not found child"); + let mut hierarchy = Hierarchy::new(OsString::new()); + for source in cx.shared.local_sources.iter() + .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root) + .ok()) { + let mut h = &mut hierarchy; + let mut elems = source.components() + .filter_map(|s| { + match s { + Component::Normal(s) => Some(s.to_owned()), + _ => None, + } + }) + .peekable(); + loop { + let cur_elem = elems.next().expect("empty file path"); + if elems.peek().is_none() { + h.elems.insert(cur_elem); + break; + } else { + let e = cur_elem.clone(); + h.children.entry(cur_elem.clone()).or_insert_with(|| Hierarchy::new(e)); + h = h.children.get_mut(&cur_elem).expect("not found child"); + } } } - } - let dst = cx.dst.join("source-files.js"); - let (mut all_sources, _krates) = try_err!(collect(&dst, &krate.name, "sourcesIndex"), &dst); - all_sources.push(format!("sourcesIndex['{}'] = {};", &krate.name, hierarchy.to_string())); - all_sources.sort(); - let mut w = try_err!(File::create(&dst), &dst); - try_err!(writeln!(&mut w, "var N = null;var sourcesIndex = {{}};\n{}", all_sources.join("\n")), - &dst); + let dst = cx.dst.join("source-files.js"); + let (mut all_sources, _krates) = try_err!(collect(&dst, &krate.name, "sourcesIndex"), &dst); + all_sources.push(format!("sourcesIndex['{}'] = {};", + &krate.name, + hierarchy.to_json_string())); + all_sources.sort(); + let mut w = try_err!(File::create(&dst), &dst); + try_err!(writeln!(&mut w, + "var N = null;var sourcesIndex = {{}};\n{}", + all_sources.join("\n")), + &dst); + } // Update the search index let dst = cx.dst.join("search-index.js"); @@ -1367,7 +1375,7 @@ impl<'a> SourceCollector<'a> { layout::render(&mut w, &self.scx.layout, &page, &(""), &Source(contents), self.scx.css_file_extension.is_some(), - &self.scx.themes, &["source-files.js", "source-script.js"])?; + &self.scx.themes, &["source-files", "source-script"])?; w.flush()?; self.scx.local_sources.insert(p.clone(), href); Ok(()) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 5dbba3ebab5..902c492105f 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1464,25 +1464,28 @@ kbd { #sidebar-toggle { position: fixed; top: 30px; - right: 300px; + left: 300px; z-index: 10; padding: 3px; - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; cursor: pointer; font-weight: bold; - transition: right 1s; + transition: left .5s; font-size: 1.2em; + border: 1px solid; + border-left: 0; } #source-sidebar { position: fixed; top: 0; bottom: 0; - right: 0; + left: 0; width: 300px; z-index: 1; overflow: auto; - transition: right 1s; + transition: left .5s; + border-right: 1px solid; } #source-sidebar > .title { font-size: 1.5em; @@ -1495,6 +1498,11 @@ div.children { padding-left: 27px; display: none; } +div.name { + cursor: pointer; + position: relative; + margin-left: 16px; +} div.files > a { display: block; padding: 0 3px; @@ -1507,10 +1515,13 @@ div.name.expand + .children { } div.name::before { content: "\25B6"; - display: inline-block; - padding-right: 4px; + padding-left: 4px; font-size: 0.7em; + position: absolute; + left: -16px; + top: 4px; } div.name.expand::before { transform: rotate(90deg); + left: -14px; } diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js index 59b82361c09..f8e0cf196fb 100644 --- a/src/librustdoc/html/static/source-script.js +++ b/src/librustdoc/html/static/source-script.js @@ -72,21 +72,21 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) { children.appendChild(files); parent.appendChild(name); parent.appendChild(children); - return hasFoundFile === true && search.currentFile !== null; + return hasFoundFile === true && currentFile.startsWith(fullPath); } function toggleSidebar() { var sidebar = document.getElementById("source-sidebar"); var child = this.children[0].children[0]; - if (child.innerText === "<") { - sidebar.style.right = ""; - this.style.right = ""; - child.innerText = ">"; + if (child.innerText === ">") { + sidebar.style.left = ""; + this.style.left = ""; + child.innerText = "<"; updateLocalStorage("rustdoc-source-sidebar-hidden", "false"); } else { - sidebar.style.right = "-300px"; - this.style.right = "0"; - child.innerText = "<"; + sidebar.style.left = "-300px"; + this.style.left = "0"; + child.innerText = ">"; updateLocalStorage("rustdoc-source-sidebar-hidden", "true"); } } @@ -102,10 +102,10 @@ function createSidebarToggle() { var inner2 = document.createElement("div"); inner2.style.marginTop = "-2px"; if (getCurrentValue("rustdoc-source-sidebar-hidden") === "true") { - inner2.innerText = "<"; - sidebarToggle.style.right = "0"; - } else { inner2.innerText = ">"; + sidebarToggle.style.left = "0"; + } else { + inner2.innerText = "<"; } inner1.appendChild(inner2); @@ -125,7 +125,7 @@ function createSourceSidebar() { var sidebar = document.createElement("div"); sidebar.id = "source-sidebar"; if (getCurrentValue("rustdoc-source-sidebar-hidden") === "true") { - sidebar.style.right = "-300px"; + sidebar.style.left = "-300px"; } var currentFile = getCurrentFilePath(); diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 3baa082bd0e..ee29f15d686 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -109,3 +109,9 @@ pub mod source_code_pro { /// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font. pub static LICENSE: &'static [u8] = include_bytes!("static/SourceCodePro-LICENSE.txt"); } + +/// Files related to the sidebar in rustdoc sources. +pub mod sidebar { + /// File script to handle sidebar. + pub static SOURCE_SCRIPT: &'static str = include_str!("static/source-script.js"); +} From 98cd2ad4ea84408ecd9d064f4bd90fe406fb7ddd Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 12 Nov 2018 08:30:52 +0100 Subject: [PATCH 0195/1984] Move some methods from `Memory` to `Allocation` --- src/librustc/mir/interpret/allocation.rs | 84 ++++++++++++++++++++++++ src/librustc_mir/interpret/memory.rs | 84 ------------------------ 2 files changed, 84 insertions(+), 84 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 3250ea266a5..1a88a959b4e 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -49,6 +49,90 @@ pub struct Allocation { pub extra: Extra, } +/// Byte accessors +impl<'tcx, Tag, Extra> Allocation { + /// The last argument controls whether we error out when there are undefined + /// or pointer bytes. You should never call this, call `get_bytes` or + /// `get_bytes_with_undef_and_ptr` instead, + /// + /// This function also guarantees that the resulting pointer will remain stable + /// even when new allocations are pushed to the `HashMap`. `copy_repeatedly` relies + /// on that. + fn get_bytes_internal( + &self, + ptr: Pointer, + size: Size, + align: Align, + check_defined_and_ptr: bool, + ) -> EvalResult<'tcx, &[u8]> { + assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); + self.check_align(ptr.into(), align)?; + self.check_bounds(ptr, size, InboundsCheck::Live)?; + + if check_defined_and_ptr { + self.check_defined(ptr, size)?; + self.check_relocations(ptr, size)?; + } else { + // We still don't want relocations on the *edges* + self.check_relocation_edges(ptr, size)?; + } + + let alloc = self.get(ptr.alloc_id)?; + AllocationExtra::memory_read(alloc, ptr, size)?; + + assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); + assert_eq!(size.bytes() as usize as u64, size.bytes()); + let offset = ptr.offset.bytes() as usize; + Ok(&alloc.bytes[offset..offset + size.bytes() as usize]) + } + + #[inline] + fn get_bytes( + &self, + ptr: Pointer, + size: Size, + align: Align + ) -> EvalResult<'tcx, &[u8]> { + self.get_bytes_internal(ptr, size, align, true) + } + + /// It is the caller's responsibility to handle undefined and pointer bytes. + /// However, this still checks that there are no relocations on the *edges*. + #[inline] + fn get_bytes_with_undef_and_ptr( + &self, + ptr: Pointer, + size: Size, + align: Align + ) -> EvalResult<'tcx, &[u8]> { + self.get_bytes_internal(ptr, size, align, false) + } + + /// Just calling this already marks everything as defined and removes relocations, + /// so be sure to actually put data there! + fn get_bytes_mut( + &mut self, + ptr: Pointer, + size: Size, + align: Align, + ) -> EvalResult<'tcx, &mut [u8]> { + assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); + self.check_align(ptr.into(), align)?; + self.check_bounds(ptr, size, InboundsCheck::Live)?; + + self.mark_definedness(ptr, size, true)?; + self.clear_relocations(ptr, size)?; + + let alloc = self.get_mut(ptr.alloc_id)?; + AllocationExtra::memory_written(alloc, ptr, size)?; + + assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); + assert_eq!(size.bytes() as usize as u64, size.bytes()); + let offset = ptr.offset.bytes() as usize; + Ok(&mut alloc.bytes[offset..offset + size.bytes() as usize]) + } +} + pub trait AllocationExtra: ::std::fmt::Debug + Default + Clone { /// Hook for performing extra checks on a memory read access. /// diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 898600d8322..759892451bd 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -609,90 +609,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } } -/// Byte accessors -impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { - /// The last argument controls whether we error out when there are undefined - /// or pointer bytes. You should never call this, call `get_bytes` or - /// `get_bytes_with_undef_and_ptr` instead, - /// - /// This function also guarantees that the resulting pointer will remain stable - /// even when new allocations are pushed to the `HashMap`. `copy_repeatedly` relies - /// on that. - fn get_bytes_internal( - &self, - ptr: Pointer, - size: Size, - align: Align, - check_defined_and_ptr: bool, - ) -> EvalResult<'tcx, &[u8]> { - assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); - self.check_align(ptr.into(), align)?; - self.check_bounds(ptr, size, InboundsCheck::Live)?; - - if check_defined_and_ptr { - self.check_defined(ptr, size)?; - self.check_relocations(ptr, size)?; - } else { - // We still don't want relocations on the *edges* - self.check_relocation_edges(ptr, size)?; - } - - let alloc = self.get(ptr.alloc_id)?; - AllocationExtra::memory_read(alloc, ptr, size)?; - - assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); - assert_eq!(size.bytes() as usize as u64, size.bytes()); - let offset = ptr.offset.bytes() as usize; - Ok(&alloc.bytes[offset..offset + size.bytes() as usize]) - } - - #[inline] - fn get_bytes( - &self, - ptr: Pointer, - size: Size, - align: Align - ) -> EvalResult<'tcx, &[u8]> { - self.get_bytes_internal(ptr, size, align, true) - } - - /// It is the caller's responsibility to handle undefined and pointer bytes. - /// However, this still checks that there are no relocations on the *edges*. - #[inline] - fn get_bytes_with_undef_and_ptr( - &self, - ptr: Pointer, - size: Size, - align: Align - ) -> EvalResult<'tcx, &[u8]> { - self.get_bytes_internal(ptr, size, align, false) - } - - /// Just calling this already marks everything as defined and removes relocations, - /// so be sure to actually put data there! - fn get_bytes_mut( - &mut self, - ptr: Pointer, - size: Size, - align: Align, - ) -> EvalResult<'tcx, &mut [u8]> { - assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); - self.check_align(ptr.into(), align)?; - self.check_bounds(ptr, size, InboundsCheck::Live)?; - - self.mark_definedness(ptr, size, true)?; - self.clear_relocations(ptr, size)?; - - let alloc = self.get_mut(ptr.alloc_id)?; - AllocationExtra::memory_written(alloc, ptr, size)?; - - assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); - assert_eq!(size.bytes() as usize as u64, size.bytes()); - let offset = ptr.offset.bytes() as usize; - Ok(&mut alloc.bytes[offset..offset + size.bytes() as usize]) - } -} - /// Interning (for CTFE) impl<'a, 'mir, 'tcx, M> Memory<'a, 'mir, 'tcx, M> where From d40a7713d3f044dc6f590acfc55f74f44f8295e8 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 12 Nov 2018 08:32:30 +0100 Subject: [PATCH 0196/1984] Preliminary code adjustment to let the compiler complain about missing methods --- src/librustc/mir/interpret/allocation.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 1a88a959b4e..669302852d4 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -60,7 +60,7 @@ impl<'tcx, Tag, Extra> Allocation { /// on that. fn get_bytes_internal( &self, - ptr: Pointer, + ptr: Pointer, size: Size, align: Align, check_defined_and_ptr: bool, @@ -89,7 +89,7 @@ impl<'tcx, Tag, Extra> Allocation { #[inline] fn get_bytes( &self, - ptr: Pointer, + ptr: Pointer, size: Size, align: Align ) -> EvalResult<'tcx, &[u8]> { @@ -101,7 +101,7 @@ impl<'tcx, Tag, Extra> Allocation { #[inline] fn get_bytes_with_undef_and_ptr( &self, - ptr: Pointer, + ptr: Pointer, size: Size, align: Align ) -> EvalResult<'tcx, &[u8]> { @@ -112,7 +112,7 @@ impl<'tcx, Tag, Extra> Allocation { /// so be sure to actually put data there! fn get_bytes_mut( &mut self, - ptr: Pointer, + ptr: Pointer, size: Size, align: Align, ) -> EvalResult<'tcx, &mut [u8]> { From eb30ce8acb6617fbe6182a3b5b9078dea4027a90 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 12 Nov 2018 08:34:04 +0100 Subject: [PATCH 0197/1984] Move relocation methods from `Memory` to `Allocation` --- src/librustc/mir/interpret/allocation.rs | 73 ++++++++++++++++++++++++ src/librustc_mir/interpret/memory.rs | 73 ------------------------ 2 files changed, 73 insertions(+), 73 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 669302852d4..2334ca2f91a 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -133,6 +133,79 @@ impl<'tcx, Tag, Extra> Allocation { } } +/// Relocations +impl<'tcx, Tag, Extra> Allocation { + /// Return all relocations overlapping with the given ptr-offset pair. + fn relocations( + &self, + ptr: Pointer, + size: Size, + ) -> EvalResult<'tcx, &[(Size, (M::PointerTag, AllocId))]> { + // We have to go back `pointer_size - 1` bytes, as that one would still overlap with + // the beginning of this range. + let start = ptr.offset.bytes().saturating_sub(self.pointer_size().bytes() - 1); + let end = ptr.offset + size; // this does overflow checking + Ok(self.get(ptr.alloc_id)?.relocations.range(Size::from_bytes(start)..end)) + } + + /// Check that there ar eno relocations overlapping with the given range. + #[inline(always)] + fn check_relocations(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { + if self.relocations(ptr, size)?.len() != 0 { + err!(ReadPointerAsBytes) + } else { + Ok(()) + } + } + + /// Remove all relocations inside the given range. + /// If there are relocations overlapping with the edges, they + /// are removed as well *and* the bytes they cover are marked as + /// uninitialized. This is a somewhat odd "spooky action at a distance", + /// but it allows strictly more code to run than if we would just error + /// immediately in that case. + fn clear_relocations(&mut self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { + // Find the start and end of the given range and its outermost relocations. + let (first, last) = { + // Find all relocations overlapping the given range. + let relocations = self.relocations(ptr, size)?; + if relocations.is_empty() { + return Ok(()); + } + + (relocations.first().unwrap().0, + relocations.last().unwrap().0 + self.pointer_size()) + }; + let start = ptr.offset; + let end = start + size; + + let alloc = self.get_mut(ptr.alloc_id)?; + + // Mark parts of the outermost relocations as undefined if they partially fall outside the + // given range. + if first < start { + alloc.undef_mask.set_range(first, start, false); + } + if last > end { + alloc.undef_mask.set_range(end, last, false); + } + + // Forget all the relocations. + alloc.relocations.remove_range(first..last); + + Ok(()) + } + + /// Error if there are relocations overlapping with the edges of the + /// given memory range. + #[inline] + fn check_relocation_edges(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { + self.check_relocations(ptr, Size::ZERO)?; + self.check_relocations(ptr.offset(size, self)?, Size::ZERO)?; + Ok(()) + } +} + pub trait AllocationExtra: ::std::fmt::Debug + Default + Clone { /// Hook for performing extra checks on a memory read access. /// diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 759892451bd..cb52e595e02 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -955,79 +955,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } } -/// Relocations -impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { - /// Return all relocations overlapping with the given ptr-offset pair. - fn relocations( - &self, - ptr: Pointer, - size: Size, - ) -> EvalResult<'tcx, &[(Size, (M::PointerTag, AllocId))]> { - // We have to go back `pointer_size - 1` bytes, as that one would still overlap with - // the beginning of this range. - let start = ptr.offset.bytes().saturating_sub(self.pointer_size().bytes() - 1); - let end = ptr.offset + size; // this does overflow checking - Ok(self.get(ptr.alloc_id)?.relocations.range(Size::from_bytes(start)..end)) - } - - /// Check that there ar eno relocations overlapping with the given range. - #[inline(always)] - fn check_relocations(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { - if self.relocations(ptr, size)?.len() != 0 { - err!(ReadPointerAsBytes) - } else { - Ok(()) - } - } - - /// Remove all relocations inside the given range. - /// If there are relocations overlapping with the edges, they - /// are removed as well *and* the bytes they cover are marked as - /// uninitialized. This is a somewhat odd "spooky action at a distance", - /// but it allows strictly more code to run than if we would just error - /// immediately in that case. - fn clear_relocations(&mut self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { - // Find the start and end of the given range and its outermost relocations. - let (first, last) = { - // Find all relocations overlapping the given range. - let relocations = self.relocations(ptr, size)?; - if relocations.is_empty() { - return Ok(()); - } - - (relocations.first().unwrap().0, - relocations.last().unwrap().0 + self.pointer_size()) - }; - let start = ptr.offset; - let end = start + size; - - let alloc = self.get_mut(ptr.alloc_id)?; - - // Mark parts of the outermost relocations as undefined if they partially fall outside the - // given range. - if first < start { - alloc.undef_mask.set_range(first, start, false); - } - if last > end { - alloc.undef_mask.set_range(end, last, false); - } - - // Forget all the relocations. - alloc.relocations.remove_range(first..last); - - Ok(()) - } - - /// Error if there are relocations overlapping with the edges of the - /// given memory range. - #[inline] - fn check_relocation_edges(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { - self.check_relocations(ptr, Size::ZERO)?; - self.check_relocations(ptr.offset(size, self)?, Size::ZERO)?; - Ok(()) - } -} - /// Undefined bytes impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // FIXME: Add a fast version for the common, nonoverlapping case From d98c46ce57d562ebcfb01ec814ff8d90d47ff7ea Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 12 Nov 2018 08:35:32 +0100 Subject: [PATCH 0198/1984] Move undef mask methods from `Memory` to `Allocation` --- src/librustc/mir/interpret/allocation.rs | 33 ++++++++++++++++++++++++ src/librustc_mir/interpret/memory.rs | 29 --------------------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 2334ca2f91a..ad4bf415b8d 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -206,6 +206,39 @@ impl<'tcx, Tag, Extra> Allocation { } } + +/// Undefined bytes +impl<'tcx, Tag, Extra> Allocation { + /// Checks that a range of bytes is defined. If not, returns the `ReadUndefBytes` + /// error which will report the first byte which is undefined. + #[inline] + fn check_defined(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { + let alloc = self.get(ptr.alloc_id)?; + alloc.undef_mask.is_range_defined( + ptr.offset, + ptr.offset + size, + ).or_else(|idx| err!(ReadUndefBytes(idx))) + } + + pub fn mark_definedness( + &mut self, + ptr: Pointer, + size: Size, + new_state: bool, + ) -> EvalResult<'tcx> { + if size.bytes() == 0 { + return Ok(()); + } + let alloc = self.get_mut(ptr.alloc_id)?; + alloc.undef_mask.set_range( + ptr.offset, + ptr.offset + size, + new_state, + ); + Ok(()) + } +} + pub trait AllocationExtra: ::std::fmt::Debug + Default + Clone { /// Hook for performing extra checks on a memory read access. /// diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index cb52e595e02..d8ae107a22b 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -984,33 +984,4 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok(()) } - - /// Checks that a range of bytes is defined. If not, returns the `ReadUndefBytes` - /// error which will report the first byte which is undefined. - #[inline] - fn check_defined(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { - let alloc = self.get(ptr.alloc_id)?; - alloc.undef_mask.is_range_defined( - ptr.offset, - ptr.offset + size, - ).or_else(|idx| err!(ReadUndefBytes(idx))) - } - - pub fn mark_definedness( - &mut self, - ptr: Pointer, - size: Size, - new_state: bool, - ) -> EvalResult<'tcx> { - if size.bytes() == 0 { - return Ok(()); - } - let alloc = self.get_mut(ptr.alloc_id)?; - alloc.undef_mask.set_range( - ptr.offset, - ptr.offset + size, - new_state, - ); - Ok(()) - } } From 7c9d786e5007004917d73749fad32bc3bff94cce Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 12 Nov 2018 08:37:54 +0100 Subject: [PATCH 0199/1984] Move alignment and bounds check from `Memory` to `Allocation` --- src/librustc/mir/interpret/allocation.rs | 45 ++++++++++++++++++++++++ src/librustc_mir/interpret/memory.rs | 42 ---------------------- 2 files changed, 45 insertions(+), 42 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index ad4bf415b8d..b2737ae203f 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -49,6 +49,51 @@ pub struct Allocation { pub extra: Extra, } +/// Alignment and bounds checks +impl<'tcx, Tag, Extra> Allocation { + /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end + /// of an allocation (i.e., at the first *inaccessible* location) *is* considered + /// in-bounds! This follows C's/LLVM's rules. `check` indicates whether we + /// additionally require the pointer to be pointing to a *live* (still allocated) + /// allocation. + /// If you want to check bounds before doing a memory access, better use `check_bounds`. + pub fn check_bounds_ptr( + &self, + ptr: Pointer, + check: InboundsCheck, + ) -> EvalResult<'tcx> { + let allocation_size = match check { + InboundsCheck::Live => { + let alloc = self.get(ptr.alloc_id)?; + alloc.bytes.len() as u64 + } + InboundsCheck::MaybeDead => { + self.get_size_and_align(ptr.alloc_id).0.bytes() + } + }; + if ptr.offset.bytes() > allocation_size { + return err!(PointerOutOfBounds { + ptr: ptr.erase_tag(), + check, + allocation_size: Size::from_bytes(allocation_size), + }); + } + Ok(()) + } + + /// Check if the memory range beginning at `ptr` and of size `Size` is "in-bounds". + #[inline(always)] + pub fn check_bounds( + &self, + ptr: Pointer, + size: Size, + check: InboundsCheck, + ) -> EvalResult<'tcx> { + // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow) + self.check_bounds_ptr(ptr.offset(size, &*self)?, check) + } +} + /// Byte accessors impl<'tcx, Tag, Extra> Allocation { /// The last argument controls whether we error out when there are undefined diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index d8ae107a22b..9f8e8fc921a 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -284,48 +284,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { }) } } - - /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end - /// of an allocation (i.e., at the first *inaccessible* location) *is* considered - /// in-bounds! This follows C's/LLVM's rules. `check` indicates whether we - /// additionally require the pointer to be pointing to a *live* (still allocated) - /// allocation. - /// If you want to check bounds before doing a memory access, better use `check_bounds`. - pub fn check_bounds_ptr( - &self, - ptr: Pointer, - check: InboundsCheck, - ) -> EvalResult<'tcx> { - let allocation_size = match check { - InboundsCheck::Live => { - let alloc = self.get(ptr.alloc_id)?; - alloc.bytes.len() as u64 - } - InboundsCheck::MaybeDead => { - self.get_size_and_align(ptr.alloc_id).0.bytes() - } - }; - if ptr.offset.bytes() > allocation_size { - return err!(PointerOutOfBounds { - ptr: ptr.erase_tag(), - check, - allocation_size: Size::from_bytes(allocation_size), - }); - } - Ok(()) - } - - /// Check if the memory range beginning at `ptr` and of size `Size` is "in-bounds". - #[inline(always)] - pub fn check_bounds( - &self, - ptr: Pointer, - size: Size, - check: InboundsCheck, - ) -> EvalResult<'tcx> { - // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow) - self.check_bounds_ptr(ptr.offset(size, &*self)?, check) - } } /// Allocation accessors From c392fbbbf16981dc6368de7ea6a8797892221283 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 12 Nov 2018 08:38:35 +0100 Subject: [PATCH 0200/1984] Adjust generics to `Allocation` parameters --- src/librustc/mir/interpret/allocation.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index b2737ae203f..05f9f482d53 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -59,7 +59,7 @@ impl<'tcx, Tag, Extra> Allocation { /// If you want to check bounds before doing a memory access, better use `check_bounds`. pub fn check_bounds_ptr( &self, - ptr: Pointer, + ptr: Pointer, check: InboundsCheck, ) -> EvalResult<'tcx> { let allocation_size = match check { @@ -85,7 +85,7 @@ impl<'tcx, Tag, Extra> Allocation { #[inline(always)] pub fn check_bounds( &self, - ptr: Pointer, + ptr: Pointer, size: Size, check: InboundsCheck, ) -> EvalResult<'tcx> { @@ -183,9 +183,9 @@ impl<'tcx, Tag, Extra> Allocation { /// Return all relocations overlapping with the given ptr-offset pair. fn relocations( &self, - ptr: Pointer, + ptr: Pointer, size: Size, - ) -> EvalResult<'tcx, &[(Size, (M::PointerTag, AllocId))]> { + ) -> EvalResult<'tcx, &[(Size, (Tag, AllocId))]> { // We have to go back `pointer_size - 1` bytes, as that one would still overlap with // the beginning of this range. let start = ptr.offset.bytes().saturating_sub(self.pointer_size().bytes() - 1); @@ -195,7 +195,7 @@ impl<'tcx, Tag, Extra> Allocation { /// Check that there ar eno relocations overlapping with the given range. #[inline(always)] - fn check_relocations(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { + fn check_relocations(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { if self.relocations(ptr, size)?.len() != 0 { err!(ReadPointerAsBytes) } else { @@ -209,7 +209,7 @@ impl<'tcx, Tag, Extra> Allocation { /// uninitialized. This is a somewhat odd "spooky action at a distance", /// but it allows strictly more code to run than if we would just error /// immediately in that case. - fn clear_relocations(&mut self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { + fn clear_relocations(&mut self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { // Find the start and end of the given range and its outermost relocations. let (first, last) = { // Find all relocations overlapping the given range. @@ -244,7 +244,7 @@ impl<'tcx, Tag, Extra> Allocation { /// Error if there are relocations overlapping with the edges of the /// given memory range. #[inline] - fn check_relocation_edges(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { + fn check_relocation_edges(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { self.check_relocations(ptr, Size::ZERO)?; self.check_relocations(ptr.offset(size, self)?, Size::ZERO)?; Ok(()) @@ -257,7 +257,7 @@ impl<'tcx, Tag, Extra> Allocation { /// Checks that a range of bytes is defined. If not, returns the `ReadUndefBytes` /// error which will report the first byte which is undefined. #[inline] - fn check_defined(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { + fn check_defined(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { let alloc = self.get(ptr.alloc_id)?; alloc.undef_mask.is_range_defined( ptr.offset, @@ -267,7 +267,7 @@ impl<'tcx, Tag, Extra> Allocation { pub fn mark_definedness( &mut self, - ptr: Pointer, + ptr: Pointer, size: Size, new_state: bool, ) -> EvalResult<'tcx> { From 04210f3e169b31613f70e5de9550a4f46039e7bc Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 12 Nov 2018 08:39:04 +0100 Subject: [PATCH 0201/1984] Access `self` instead of `alloc` --- src/librustc/mir/interpret/allocation.rs | 44 ++++++++---------------- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 05f9f482d53..aba0da32d45 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -60,21 +60,12 @@ impl<'tcx, Tag, Extra> Allocation { pub fn check_bounds_ptr( &self, ptr: Pointer, - check: InboundsCheck, ) -> EvalResult<'tcx> { - let allocation_size = match check { - InboundsCheck::Live => { - let alloc = self.get(ptr.alloc_id)?; - alloc.bytes.len() as u64 - } - InboundsCheck::MaybeDead => { - self.get_size_and_align(ptr.alloc_id).0.bytes() - } - }; + let allocation_size = self.bytes.len() as u64; if ptr.offset.bytes() > allocation_size { return err!(PointerOutOfBounds { ptr: ptr.erase_tag(), - check, + check: InboundsCheck::Live, allocation_size: Size::from_bytes(allocation_size), }); } @@ -87,15 +78,14 @@ impl<'tcx, Tag, Extra> Allocation { &self, ptr: Pointer, size: Size, - check: InboundsCheck, ) -> EvalResult<'tcx> { // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow) - self.check_bounds_ptr(ptr.offset(size, &*self)?, check) + self.check_bounds_ptr(ptr.offset(size, &*self)?) } } /// Byte accessors -impl<'tcx, Tag, Extra> Allocation { +impl<'tcx, Tag, Extra: AllocationExtra> Allocation { /// The last argument controls whether we error out when there are undefined /// or pointer bytes. You should never call this, call `get_bytes` or /// `get_bytes_with_undef_and_ptr` instead, @@ -122,13 +112,12 @@ impl<'tcx, Tag, Extra> Allocation { self.check_relocation_edges(ptr, size)?; } - let alloc = self.get(ptr.alloc_id)?; - AllocationExtra::memory_read(alloc, ptr, size)?; + AllocationExtra::memory_read(self, ptr, size)?; assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); assert_eq!(size.bytes() as usize as u64, size.bytes()); let offset = ptr.offset.bytes() as usize; - Ok(&alloc.bytes[offset..offset + size.bytes() as usize]) + Ok(&self.bytes[offset..offset + size.bytes() as usize]) } #[inline] @@ -168,13 +157,12 @@ impl<'tcx, Tag, Extra> Allocation { self.mark_definedness(ptr, size, true)?; self.clear_relocations(ptr, size)?; - let alloc = self.get_mut(ptr.alloc_id)?; - AllocationExtra::memory_written(alloc, ptr, size)?; + AllocationExtra::memory_written(self, ptr, size)?; assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); assert_eq!(size.bytes() as usize as u64, size.bytes()); let offset = ptr.offset.bytes() as usize; - Ok(&mut alloc.bytes[offset..offset + size.bytes() as usize]) + Ok(&mut self.bytes[offset..offset + size.bytes() as usize]) } } @@ -190,7 +178,7 @@ impl<'tcx, Tag, Extra> Allocation { // the beginning of this range. let start = ptr.offset.bytes().saturating_sub(self.pointer_size().bytes() - 1); let end = ptr.offset + size; // this does overflow checking - Ok(self.get(ptr.alloc_id)?.relocations.range(Size::from_bytes(start)..end)) + Ok(self.relocations.range(Size::from_bytes(start)..end)) } /// Check that there ar eno relocations overlapping with the given range. @@ -224,19 +212,17 @@ impl<'tcx, Tag, Extra> Allocation { let start = ptr.offset; let end = start + size; - let alloc = self.get_mut(ptr.alloc_id)?; - // Mark parts of the outermost relocations as undefined if they partially fall outside the // given range. if first < start { - alloc.undef_mask.set_range(first, start, false); + self.undef_mask.set_range(first, start, false); } if last > end { - alloc.undef_mask.set_range(end, last, false); + self.undef_mask.set_range(end, last, false); } // Forget all the relocations. - alloc.relocations.remove_range(first..last); + self.relocations.remove_range(first..last); Ok(()) } @@ -258,8 +244,7 @@ impl<'tcx, Tag, Extra> Allocation { /// error which will report the first byte which is undefined. #[inline] fn check_defined(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { - let alloc = self.get(ptr.alloc_id)?; - alloc.undef_mask.is_range_defined( + self.undef_mask.is_range_defined( ptr.offset, ptr.offset + size, ).or_else(|idx| err!(ReadUndefBytes(idx))) @@ -274,8 +259,7 @@ impl<'tcx, Tag, Extra> Allocation { if size.bytes() == 0 { return Ok(()); } - let alloc = self.get_mut(ptr.alloc_id)?; - alloc.undef_mask.set_range( + self.undef_mask.set_range( ptr.offset, ptr.offset + size, new_state, From ad11856431ea3c0808951eed9fcbefbd82590ef2 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 12 Nov 2018 08:56:41 +0100 Subject: [PATCH 0202/1984] Fiddle a `HasDataLayout` through the allocation methods --- src/librustc/mir/interpret/allocation.rs | 60 ++++++++++++++++-------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index aba0da32d45..1856232573c 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -18,6 +18,7 @@ use std::iter; use mir; use std::ops::{Deref, DerefMut}; use rustc_data_structures::sorted_map::SortedMap; +use rustc_target::abi::HasDataLayout; /// Used by `check_bounds` to indicate whether the pointer needs to be just inbounds /// or also inbounds of a *live* allocation. @@ -76,16 +77,17 @@ impl<'tcx, Tag, Extra> Allocation { #[inline(always)] pub fn check_bounds( &self, + cx: &impl HasDataLayout, ptr: Pointer, size: Size, ) -> EvalResult<'tcx> { // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow) - self.check_bounds_ptr(ptr.offset(size, &*self)?) + self.check_bounds_ptr(ptr.offset(size, cx)?) } } /// Byte accessors -impl<'tcx, Tag, Extra: AllocationExtra> Allocation { +impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// The last argument controls whether we error out when there are undefined /// or pointer bytes. You should never call this, call `get_bytes` or /// `get_bytes_with_undef_and_ptr` instead, @@ -95,6 +97,7 @@ impl<'tcx, Tag, Extra: AllocationExtra> Allocation { /// on that. fn get_bytes_internal( &self, + cx: &impl HasDataLayout, ptr: Pointer, size: Size, align: Align, @@ -102,14 +105,14 @@ impl<'tcx, Tag, Extra: AllocationExtra> Allocation { ) -> EvalResult<'tcx, &[u8]> { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); self.check_align(ptr.into(), align)?; - self.check_bounds(ptr, size, InboundsCheck::Live)?; + self.check_bounds(cx, ptr, size)?; if check_defined_and_ptr { self.check_defined(ptr, size)?; - self.check_relocations(ptr, size)?; + self.check_relocations(cx, ptr, size)?; } else { // We still don't want relocations on the *edges* - self.check_relocation_edges(ptr, size)?; + self.check_relocation_edges(cx, ptr, size)?; } AllocationExtra::memory_read(self, ptr, size)?; @@ -123,11 +126,12 @@ impl<'tcx, Tag, Extra: AllocationExtra> Allocation { #[inline] fn get_bytes( &self, + cx: &impl HasDataLayout, ptr: Pointer, size: Size, align: Align ) -> EvalResult<'tcx, &[u8]> { - self.get_bytes_internal(ptr, size, align, true) + self.get_bytes_internal(cx, ptr, size, align, true) } /// It is the caller's responsibility to handle undefined and pointer bytes. @@ -135,27 +139,29 @@ impl<'tcx, Tag, Extra: AllocationExtra> Allocation { #[inline] fn get_bytes_with_undef_and_ptr( &self, + cx: &impl HasDataLayout, ptr: Pointer, size: Size, align: Align ) -> EvalResult<'tcx, &[u8]> { - self.get_bytes_internal(ptr, size, align, false) + self.get_bytes_internal(cx, ptr, size, align, false) } /// Just calling this already marks everything as defined and removes relocations, /// so be sure to actually put data there! fn get_bytes_mut( &mut self, + cx: &impl HasDataLayout, ptr: Pointer, size: Size, align: Align, ) -> EvalResult<'tcx, &mut [u8]> { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); self.check_align(ptr.into(), align)?; - self.check_bounds(ptr, size, InboundsCheck::Live)?; + self.check_bounds(cx, ptr, size)?; self.mark_definedness(ptr, size, true)?; - self.clear_relocations(ptr, size)?; + self.clear_relocations(cx, ptr, size)?; AllocationExtra::memory_written(self, ptr, size)?; @@ -167,24 +173,30 @@ impl<'tcx, Tag, Extra: AllocationExtra> Allocation { } /// Relocations -impl<'tcx, Tag, Extra> Allocation { +impl<'tcx, Tag: Copy, Extra> Allocation { /// Return all relocations overlapping with the given ptr-offset pair. fn relocations( &self, + cx: &impl HasDataLayout, ptr: Pointer, size: Size, ) -> EvalResult<'tcx, &[(Size, (Tag, AllocId))]> { // We have to go back `pointer_size - 1` bytes, as that one would still overlap with // the beginning of this range. - let start = ptr.offset.bytes().saturating_sub(self.pointer_size().bytes() - 1); + let start = ptr.offset.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1); let end = ptr.offset + size; // this does overflow checking Ok(self.relocations.range(Size::from_bytes(start)..end)) } /// Check that there ar eno relocations overlapping with the given range. #[inline(always)] - fn check_relocations(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { - if self.relocations(ptr, size)?.len() != 0 { + fn check_relocations( + &self, + cx: &impl HasDataLayout, + ptr: Pointer, + size: Size, + ) -> EvalResult<'tcx> { + if self.relocations(cx, ptr, size)?.len() != 0 { err!(ReadPointerAsBytes) } else { Ok(()) @@ -197,17 +209,22 @@ impl<'tcx, Tag, Extra> Allocation { /// uninitialized. This is a somewhat odd "spooky action at a distance", /// but it allows strictly more code to run than if we would just error /// immediately in that case. - fn clear_relocations(&mut self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { + fn clear_relocations( + &mut self, + cx: &impl HasDataLayout, + ptr: Pointer, + size: Size, + ) -> EvalResult<'tcx> { // Find the start and end of the given range and its outermost relocations. let (first, last) = { // Find all relocations overlapping the given range. - let relocations = self.relocations(ptr, size)?; + let relocations = self.relocations(cx, ptr, size)?; if relocations.is_empty() { return Ok(()); } (relocations.first().unwrap().0, - relocations.last().unwrap().0 + self.pointer_size()) + relocations.last().unwrap().0 + cx.data_layout().pointer_size) }; let start = ptr.offset; let end = start + size; @@ -230,9 +247,14 @@ impl<'tcx, Tag, Extra> Allocation { /// Error if there are relocations overlapping with the edges of the /// given memory range. #[inline] - fn check_relocation_edges(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { - self.check_relocations(ptr, Size::ZERO)?; - self.check_relocations(ptr.offset(size, self)?, Size::ZERO)?; + fn check_relocation_edges( + &self, + cx: &impl HasDataLayout, + ptr: Pointer, + size: Size, + ) -> EvalResult<'tcx> { + self.check_relocations(cx, ptr, Size::ZERO)?; + self.check_relocations(cx, ptr.offset(size, cx)?, Size::ZERO)?; Ok(()) } } From 9ecde5712ec5b393c7a0bb0074c957446ed9886b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 12 Nov 2018 09:00:41 +0100 Subject: [PATCH 0203/1984] Move some byte and scalar accessors from `Memory` to `Allocation` --- src/librustc/mir/interpret/allocation.rs | 200 +++++++++++++++++++++++ src/librustc_mir/interpret/memory.rs | 197 ---------------------- 2 files changed, 200 insertions(+), 197 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 1856232573c..cba51981021 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -86,6 +86,206 @@ impl<'tcx, Tag, Extra> Allocation { } } +/// Reading and writing +impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { + pub fn read_c_str(&self, ptr: Pointer) -> EvalResult<'tcx, &[u8]> { + let alloc = self.get(ptr.alloc_id)?; + assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); + let offset = ptr.offset.bytes() as usize; + match alloc.bytes[offset..].iter().position(|&c| c == 0) { + Some(size) => { + let p1 = Size::from_bytes((size + 1) as u64); + self.check_relocations(ptr, p1)?; + self.check_defined(ptr, p1)?; + Ok(&alloc.bytes[offset..offset + size]) + } + None => err!(UnterminatedCString(ptr.erase_tag())), + } + } + + pub fn check_bytes( + &self, + ptr: Scalar, + size: Size, + allow_ptr_and_undef: bool, + ) -> EvalResult<'tcx> { + // Empty accesses don't need to be valid pointers, but they should still be non-NULL + let align = Align::from_bytes(1).unwrap(); + if size.bytes() == 0 { + self.check_align(ptr, align)?; + return Ok(()); + } + let ptr = ptr.to_ptr()?; + // Check bounds, align and relocations on the edges + self.get_bytes_with_undef_and_ptr(ptr, size, align)?; + // Check undef and ptr + if !allow_ptr_and_undef { + self.check_defined(ptr, size)?; + self.check_relocations(ptr, size)?; + } + Ok(()) + } + + pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> { + // Empty accesses don't need to be valid pointers, but they should still be non-NULL + let align = Align::from_bytes(1).unwrap(); + if size.bytes() == 0 { + self.check_align(ptr, align)?; + return Ok(&[]); + } + self.get_bytes(ptr.to_ptr()?, size, align) + } + + pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> { + // Empty accesses don't need to be valid pointers, but they should still be non-NULL + let align = Align::from_bytes(1).unwrap(); + if src.is_empty() { + self.check_align(ptr, align)?; + return Ok(()); + } + let bytes = self.get_bytes_mut(ptr.to_ptr()?, Size::from_bytes(src.len() as u64), align)?; + bytes.clone_from_slice(src); + Ok(()) + } + + pub fn write_repeat( + &mut self, + ptr: Scalar, + val: u8, + count: Size + ) -> EvalResult<'tcx> { + // Empty accesses don't need to be valid pointers, but they should still be non-NULL + let align = Align::from_bytes(1).unwrap(); + if count.bytes() == 0 { + self.check_align(ptr, align)?; + return Ok(()); + } + let bytes = self.get_bytes_mut(ptr.to_ptr()?, count, align)?; + for b in bytes { + *b = val; + } + Ok(()) + } + + /// Read a *non-ZST* scalar + pub fn read_scalar( + &self, + ptr: Pointer, + ptr_align: Align, + size: Size + ) -> EvalResult<'tcx, ScalarMaybeUndef> { + // get_bytes_unchecked tests alignment and relocation edges + let bytes = self.get_bytes_with_undef_and_ptr( + ptr, size, ptr_align.min(self.int_align(size)) + )?; + // Undef check happens *after* we established that the alignment is correct. + // We must not return Ok() for unaligned pointers! + if self.check_defined(ptr, size).is_err() { + // this inflates undefined bytes to the entire scalar, even if only a few + // bytes are undefined + return Ok(ScalarMaybeUndef::Undef); + } + // Now we do the actual reading + let bits = read_target_uint(self.tcx.data_layout.endian, bytes).unwrap(); + // See if we got a pointer + if size != self.pointer_size() { + // *Now* better make sure that the inside also is free of relocations. + self.check_relocations(ptr, size)?; + } else { + let alloc = self.get(ptr.alloc_id)?; + match alloc.relocations.get(&ptr.offset) { + Some(&(tag, alloc_id)) => { + let ptr = Pointer::new_with_tag(alloc_id, Size::from_bytes(bits as u64), tag); + return Ok(ScalarMaybeUndef::Scalar(ptr.into())) + } + None => {}, + } + } + // We don't. Just return the bits. + Ok(ScalarMaybeUndef::Scalar(Scalar::from_uint(bits, size))) + } + + pub fn read_ptr_sized( + &self, + ptr: Pointer, + ptr_align: Align + ) -> EvalResult<'tcx, ScalarMaybeUndef> { + self.read_scalar(ptr, ptr_align, self.pointer_size()) + } + + /// Write a *non-ZST* scalar + pub fn write_scalar( + &mut self, + ptr: Pointer, + ptr_align: Align, + val: ScalarMaybeUndef, + type_size: Size, + ) -> EvalResult<'tcx> { + let val = match val { + ScalarMaybeUndef::Scalar(scalar) => scalar, + ScalarMaybeUndef::Undef => return self.mark_definedness(ptr, type_size, false), + }; + + let bytes = match val { + Scalar::Ptr(val) => { + assert_eq!(type_size, self.pointer_size()); + val.offset.bytes() as u128 + } + + Scalar::Bits { bits, size } => { + assert_eq!(size as u64, type_size.bytes()); + debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits, + "Unexpected value of size {} when writing to memory", size); + bits + }, + }; + + { + // get_bytes_mut checks alignment + let endian = self.tcx.data_layout.endian; + let dst = self.get_bytes_mut(ptr, type_size, ptr_align)?; + write_target_uint(endian, dst, bytes).unwrap(); + } + + // See if we have to also write a relocation + match val { + Scalar::Ptr(val) => { + self.get_mut(ptr.alloc_id)?.relocations.insert( + ptr.offset, + (val.tag, val.alloc_id), + ); + } + _ => {} + } + + Ok(()) + } + + pub fn write_ptr_sized( + &mut self, + ptr: Pointer, + ptr_align: Align, + val: ScalarMaybeUndef + ) -> EvalResult<'tcx> { + let ptr_size = self.pointer_size(); + self.write_scalar(ptr.into(), ptr_align, val, ptr_size) + } + + fn int_align(&self, size: Size) -> Align { + // We assume pointer-sized integers have the same alignment as pointers. + // We also assume signed and unsigned integers of the same size have the same alignment. + let ity = match size.bytes() { + 1 => layout::I8, + 2 => layout::I16, + 4 => layout::I32, + 8 => layout::I64, + 16 => layout::I128, + _ => bug!("bad integer size: {}", size.bytes()), + }; + ity.align(self).abi + } +} + /// Byte accessors impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// The last argument controls whether we error out when there are undefined diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 9f8e8fc921a..69789637927 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -714,203 +714,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok(()) } - - pub fn read_c_str(&self, ptr: Pointer) -> EvalResult<'tcx, &[u8]> { - let alloc = self.get(ptr.alloc_id)?; - assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); - let offset = ptr.offset.bytes() as usize; - match alloc.bytes[offset..].iter().position(|&c| c == 0) { - Some(size) => { - let p1 = Size::from_bytes((size + 1) as u64); - self.check_relocations(ptr, p1)?; - self.check_defined(ptr, p1)?; - Ok(&alloc.bytes[offset..offset + size]) - } - None => err!(UnterminatedCString(ptr.erase_tag())), - } - } - - pub fn check_bytes( - &self, - ptr: Scalar, - size: Size, - allow_ptr_and_undef: bool, - ) -> EvalResult<'tcx> { - // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = Align::from_bytes(1).unwrap(); - if size.bytes() == 0 { - self.check_align(ptr, align)?; - return Ok(()); - } - let ptr = ptr.to_ptr()?; - // Check bounds, align and relocations on the edges - self.get_bytes_with_undef_and_ptr(ptr, size, align)?; - // Check undef and ptr - if !allow_ptr_and_undef { - self.check_defined(ptr, size)?; - self.check_relocations(ptr, size)?; - } - Ok(()) - } - - pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> { - // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = Align::from_bytes(1).unwrap(); - if size.bytes() == 0 { - self.check_align(ptr, align)?; - return Ok(&[]); - } - self.get_bytes(ptr.to_ptr()?, size, align) - } - - pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> { - // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = Align::from_bytes(1).unwrap(); - if src.is_empty() { - self.check_align(ptr, align)?; - return Ok(()); - } - let bytes = self.get_bytes_mut(ptr.to_ptr()?, Size::from_bytes(src.len() as u64), align)?; - bytes.clone_from_slice(src); - Ok(()) - } - - pub fn write_repeat( - &mut self, - ptr: Scalar, - val: u8, - count: Size - ) -> EvalResult<'tcx> { - // Empty accesses don't need to be valid pointers, but they should still be non-NULL - let align = Align::from_bytes(1).unwrap(); - if count.bytes() == 0 { - self.check_align(ptr, align)?; - return Ok(()); - } - let bytes = self.get_bytes_mut(ptr.to_ptr()?, count, align)?; - for b in bytes { - *b = val; - } - Ok(()) - } - - /// Read a *non-ZST* scalar - pub fn read_scalar( - &self, - ptr: Pointer, - ptr_align: Align, - size: Size - ) -> EvalResult<'tcx, ScalarMaybeUndef> { - // get_bytes_unchecked tests alignment and relocation edges - let bytes = self.get_bytes_with_undef_and_ptr( - ptr, size, ptr_align.min(self.int_align(size)) - )?; - // Undef check happens *after* we established that the alignment is correct. - // We must not return Ok() for unaligned pointers! - if self.check_defined(ptr, size).is_err() { - // this inflates undefined bytes to the entire scalar, even if only a few - // bytes are undefined - return Ok(ScalarMaybeUndef::Undef); - } - // Now we do the actual reading - let bits = read_target_uint(self.tcx.data_layout.endian, bytes).unwrap(); - // See if we got a pointer - if size != self.pointer_size() { - // *Now* better make sure that the inside also is free of relocations. - self.check_relocations(ptr, size)?; - } else { - let alloc = self.get(ptr.alloc_id)?; - match alloc.relocations.get(&ptr.offset) { - Some(&(tag, alloc_id)) => { - let ptr = Pointer::new_with_tag(alloc_id, Size::from_bytes(bits as u64), tag); - return Ok(ScalarMaybeUndef::Scalar(ptr.into())) - } - None => {}, - } - } - // We don't. Just return the bits. - Ok(ScalarMaybeUndef::Scalar(Scalar::from_uint(bits, size))) - } - - pub fn read_ptr_sized( - &self, - ptr: Pointer, - ptr_align: Align - ) -> EvalResult<'tcx, ScalarMaybeUndef> { - self.read_scalar(ptr, ptr_align, self.pointer_size()) - } - - /// Write a *non-ZST* scalar - pub fn write_scalar( - &mut self, - ptr: Pointer, - ptr_align: Align, - val: ScalarMaybeUndef, - type_size: Size, - ) -> EvalResult<'tcx> { - let val = match val { - ScalarMaybeUndef::Scalar(scalar) => scalar, - ScalarMaybeUndef::Undef => return self.mark_definedness(ptr, type_size, false), - }; - - let bytes = match val { - Scalar::Ptr(val) => { - assert_eq!(type_size, self.pointer_size()); - val.offset.bytes() as u128 - } - - Scalar::Bits { bits, size } => { - assert_eq!(size as u64, type_size.bytes()); - debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits, - "Unexpected value of size {} when writing to memory", size); - bits - }, - }; - - { - // get_bytes_mut checks alignment - let endian = self.tcx.data_layout.endian; - let dst = self.get_bytes_mut(ptr, type_size, ptr_align)?; - write_target_uint(endian, dst, bytes).unwrap(); - } - - // See if we have to also write a relocation - match val { - Scalar::Ptr(val) => { - self.get_mut(ptr.alloc_id)?.relocations.insert( - ptr.offset, - (val.tag, val.alloc_id), - ); - } - _ => {} - } - - Ok(()) - } - - pub fn write_ptr_sized( - &mut self, - ptr: Pointer, - ptr_align: Align, - val: ScalarMaybeUndef - ) -> EvalResult<'tcx> { - let ptr_size = self.pointer_size(); - self.write_scalar(ptr.into(), ptr_align, val, ptr_size) - } - - fn int_align(&self, size: Size) -> Align { - // We assume pointer-sized integers have the same alignment as pointers. - // We also assume signed and unsigned integers of the same size have the same alignment. - let ity = match size.bytes() { - 1 => layout::I8, - 2 => layout::I16, - 4 => layout::I32, - 8 => layout::I64, - 16 => layout::I128, - _ => bug!("bad integer size: {}", size.bytes()), - }; - ity.align(self).abi - } } /// Undefined bytes From 07e7804110c77d572012f913a341523bdbaac4dd Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 12 Nov 2018 13:26:53 +0100 Subject: [PATCH 0204/1984] Adjust rustc_mir::interpret to changes in `Allocation`/`Memory` methods --- src/librustc/mir/interpret/allocation.rs | 112 ++++++++++++++--------- src/librustc_mir/interpret/memory.rs | 16 +++- src/librustc_mir/interpret/operand.rs | 17 +++- src/librustc_mir/interpret/place.rs | 15 ++- src/librustc_mir/interpret/terminator.rs | 3 +- src/librustc_mir/interpret/traits.rs | 31 +++++-- src/librustc_mir/interpret/validity.rs | 28 ++++-- 7 files changed, 146 insertions(+), 76 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index cba51981021..6ef7a5a266d 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -10,9 +10,12 @@ //! The virtual memory representation of the MIR interpreter -use super::{Pointer, EvalResult, AllocId}; +use super::{ + Pointer, EvalResult, AllocId, ScalarMaybeUndef, write_target_uint, read_target_uint, Scalar, + truncate, +}; -use ty::layout::{Size, Align}; +use ty::layout::{self, Size, Align}; use syntax::ast::Mutability; use std::iter; use mir; @@ -88,16 +91,19 @@ impl<'tcx, Tag, Extra> Allocation { /// Reading and writing impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { - pub fn read_c_str(&self, ptr: Pointer) -> EvalResult<'tcx, &[u8]> { - let alloc = self.get(ptr.alloc_id)?; + pub fn read_c_str( + &self, + cx: &impl HasDataLayout, + ptr: Pointer, + ) -> EvalResult<'tcx, &[u8]> { assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); let offset = ptr.offset.bytes() as usize; - match alloc.bytes[offset..].iter().position(|&c| c == 0) { + match self.bytes[offset..].iter().position(|&c| c == 0) { Some(size) => { let p1 = Size::from_bytes((size + 1) as u64); - self.check_relocations(ptr, p1)?; + self.check_relocations(cx, ptr, p1)?; self.check_defined(ptr, p1)?; - Ok(&alloc.bytes[offset..offset + size]) + Ok(&self.bytes[offset..offset + size]) } None => err!(UnterminatedCString(ptr.erase_tag())), } @@ -105,7 +111,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { pub fn check_bytes( &self, - ptr: Scalar, + cx: &impl HasDataLayout, + ptr: Pointer, size: Size, allow_ptr_and_undef: bool, ) -> EvalResult<'tcx> { @@ -115,42 +122,54 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { self.check_align(ptr, align)?; return Ok(()); } - let ptr = ptr.to_ptr()?; // Check bounds, align and relocations on the edges - self.get_bytes_with_undef_and_ptr(ptr, size, align)?; + self.get_bytes_with_undef_and_ptr(cx, ptr, size, align)?; // Check undef and ptr if !allow_ptr_and_undef { self.check_defined(ptr, size)?; - self.check_relocations(ptr, size)?; + self.check_relocations(cx, ptr, size)?; } Ok(()) } - pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> { + pub fn read_bytes( + &self, + cx: &impl HasDataLayout, + ptr: Pointer, + size: Size, + ) -> EvalResult<'tcx, &[u8]> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL let align = Align::from_bytes(1).unwrap(); if size.bytes() == 0 { self.check_align(ptr, align)?; return Ok(&[]); } - self.get_bytes(ptr.to_ptr()?, size, align) + self.get_bytes(cx, ptr, size, align) } - pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> { + pub fn write_bytes( + &mut self, + cx: &impl HasDataLayout, + ptr: Pointer, + src: &[u8], + ) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL let align = Align::from_bytes(1).unwrap(); if src.is_empty() { self.check_align(ptr, align)?; return Ok(()); } - let bytes = self.get_bytes_mut(ptr.to_ptr()?, Size::from_bytes(src.len() as u64), align)?; + let bytes = self.get_bytes_mut( + cx, ptr, Size::from_bytes(src.len() as u64), align, + )?; bytes.clone_from_slice(src); Ok(()) } pub fn write_repeat( &mut self, - ptr: Scalar, + cx: &impl HasDataLayout, + ptr: Pointer, val: u8, count: Size ) -> EvalResult<'tcx> { @@ -160,7 +179,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { self.check_align(ptr, align)?; return Ok(()); } - let bytes = self.get_bytes_mut(ptr.to_ptr()?, count, align)?; + let bytes = self.get_bytes_mut(cx, ptr, count, align)?; for b in bytes { *b = val; } @@ -170,13 +189,14 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Read a *non-ZST* scalar pub fn read_scalar( &self, - ptr: Pointer, + cx: &impl HasDataLayout, + ptr: Pointer, ptr_align: Align, size: Size - ) -> EvalResult<'tcx, ScalarMaybeUndef> { + ) -> EvalResult<'tcx, ScalarMaybeUndef> { // get_bytes_unchecked tests alignment and relocation edges let bytes = self.get_bytes_with_undef_and_ptr( - ptr, size, ptr_align.min(self.int_align(size)) + cx, ptr, size, ptr_align.min(self.int_align(cx, size)) )?; // Undef check happens *after* we established that the alignment is correct. // We must not return Ok() for unaligned pointers! @@ -186,14 +206,13 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { return Ok(ScalarMaybeUndef::Undef); } // Now we do the actual reading - let bits = read_target_uint(self.tcx.data_layout.endian, bytes).unwrap(); + let bits = read_target_uint(cx.data_layout().endian, bytes).unwrap(); // See if we got a pointer - if size != self.pointer_size() { + if size != cx.data_layout().pointer_size { // *Now* better make sure that the inside also is free of relocations. - self.check_relocations(ptr, size)?; + self.check_relocations(cx, ptr, size)?; } else { - let alloc = self.get(ptr.alloc_id)?; - match alloc.relocations.get(&ptr.offset) { + match self.relocations.get(&ptr.offset) { Some(&(tag, alloc_id)) => { let ptr = Pointer::new_with_tag(alloc_id, Size::from_bytes(bits as u64), tag); return Ok(ScalarMaybeUndef::Scalar(ptr.into())) @@ -207,18 +226,20 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { pub fn read_ptr_sized( &self, - ptr: Pointer, + cx: &impl HasDataLayout, + ptr: Pointer, ptr_align: Align - ) -> EvalResult<'tcx, ScalarMaybeUndef> { - self.read_scalar(ptr, ptr_align, self.pointer_size()) + ) -> EvalResult<'tcx, ScalarMaybeUndef> { + self.read_scalar(cx, ptr, ptr_align, cx.data_layout().pointer_size) } /// Write a *non-ZST* scalar pub fn write_scalar( &mut self, - ptr: Pointer, + cx: &impl HasDataLayout, + ptr: Pointer, ptr_align: Align, - val: ScalarMaybeUndef, + val: ScalarMaybeUndef, type_size: Size, ) -> EvalResult<'tcx> { let val = match val { @@ -228,7 +249,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { let bytes = match val { Scalar::Ptr(val) => { - assert_eq!(type_size, self.pointer_size()); + assert_eq!(type_size, cx.data_layout().pointer_size); val.offset.bytes() as u128 } @@ -242,15 +263,15 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { { // get_bytes_mut checks alignment - let endian = self.tcx.data_layout.endian; - let dst = self.get_bytes_mut(ptr, type_size, ptr_align)?; + let endian = cx.data_layout().endian; + let dst = self.get_bytes_mut(cx, ptr, type_size, ptr_align)?; write_target_uint(endian, dst, bytes).unwrap(); } // See if we have to also write a relocation match val { Scalar::Ptr(val) => { - self.get_mut(ptr.alloc_id)?.relocations.insert( + self.relocations.insert( ptr.offset, (val.tag, val.alloc_id), ); @@ -263,15 +284,20 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { pub fn write_ptr_sized( &mut self, - ptr: Pointer, + cx: &impl HasDataLayout, + ptr: Pointer, ptr_align: Align, - val: ScalarMaybeUndef + val: ScalarMaybeUndef ) -> EvalResult<'tcx> { - let ptr_size = self.pointer_size(); - self.write_scalar(ptr.into(), ptr_align, val, ptr_size) + let ptr_size = cx.data_layout().pointer_size; + self.write_scalar(cx, ptr.into(), ptr_align, val, ptr_size) } - fn int_align(&self, size: Size) -> Align { + fn int_align( + &self, + cx: &impl HasDataLayout, + size: Size, + ) -> Align { // We assume pointer-sized integers have the same alignment as pointers. // We also assume signed and unsigned integers of the same size have the same alignment. let ity = match size.bytes() { @@ -282,7 +308,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { 16 => layout::I128, _ => bug!("bad integer size: {}", size.bytes()), }; - ity.align(self).abi + ity.align(cx).abi } } @@ -337,7 +363,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// It is the caller's responsibility to handle undefined and pointer bytes. /// However, this still checks that there are no relocations on the *edges*. #[inline] - fn get_bytes_with_undef_and_ptr( + pub fn get_bytes_with_undef_and_ptr( &self, cx: &impl HasDataLayout, ptr: Pointer, @@ -349,7 +375,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Just calling this already marks everything as defined and removes relocations, /// so be sure to actually put data there! - fn get_bytes_mut( + pub fn get_bytes_mut( &mut self, cx: &impl HasDataLayout, ptr: Pointer, @@ -375,7 +401,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Relocations impl<'tcx, Tag: Copy, Extra> Allocation { /// Return all relocations overlapping with the given ptr-offset pair. - fn relocations( + pub fn relocations( &self, cx: &impl HasDataLayout, ptr: Pointer, diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 69789637927..3119d9ed0ff 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -21,7 +21,7 @@ use std::ptr; use std::borrow::Cow; use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt}; -use rustc::ty::layout::{self, Align, TargetDataLayout, Size, HasDataLayout}; +use rustc::ty::layout::{Align, TargetDataLayout, Size, HasDataLayout}; pub use rustc::mir::interpret::{truncate, write_target_uint, read_target_uint}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; @@ -30,7 +30,7 @@ use syntax::ast::Mutability; use super::{ Pointer, AllocId, Allocation, GlobalId, AllocationExtra, InboundsCheck, EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic, - Machine, AllocMap, MayLeak, ScalarMaybeUndef, ErrorHandled, + Machine, AllocMap, MayLeak, ErrorHandled, }; #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] @@ -655,7 +655,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // (`get_bytes_with_undef_and_ptr` below checks that there are no // relocations overlapping the edges; those would not be handled correctly). let relocations = { - let relocations = self.relocations(src, size)?; + let relocations = self.get(src.alloc_id)?.relocations(self, src, size)?; let mut new_relocations = Vec::with_capacity(relocations.len() * (length as usize)); for i in 0..length { new_relocations.extend( @@ -671,9 +671,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { new_relocations }; + let tcx = self.tcx.tcx; + // This also checks alignment, and relocation edges on the src. - let src_bytes = self.get_bytes_with_undef_and_ptr(src, size, src_align)?.as_ptr(); - let dest_bytes = self.get_bytes_mut(dest, size * length, dest_align)?.as_mut_ptr(); + let src_bytes = self.get(src.alloc_id)? + .get_bytes_with_undef_and_ptr(&tcx, src, size, src_align)? + .as_ptr(); + let dest_bytes = self.get_mut(dest.alloc_id)? + .get_bytes_mut(&tcx, dest, size * length, dest_align)? + .as_mut_ptr(); // SAFE: The above indexing would have panicked if there weren't at least `size` bytes // behind `src` and `dest`. Also, we use the overlapping-safe `ptr::copy` if `src` and diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 8238d580022..3f5f0ebed72 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -278,7 +278,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let ptr = ptr.to_ptr()?; match mplace.layout.abi { layout::Abi::Scalar(..) => { - let scalar = self.memory.read_scalar(ptr, ptr_align, mplace.layout.size)?; + let scalar = self.memory + .get(ptr.alloc_id)? + .read_scalar(self, ptr, ptr_align, mplace.layout.size)?; Ok(Some(Immediate::Scalar(scalar))) } layout::Abi::ScalarPair(ref a, ref b) => { @@ -288,8 +290,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let b_offset = a_size.align_to(b.align(self).abi); assert!(b_offset.bytes() > 0); // we later use the offset to test which field to use let b_ptr = ptr.offset(b_offset, self)?.into(); - let a_val = self.memory.read_scalar(a_ptr, ptr_align, a_size)?; - let b_val = self.memory.read_scalar(b_ptr, ptr_align, b_size)?; + let a_val = self.memory + .get(ptr.alloc_id)? + .read_scalar(self, a_ptr, ptr_align, a_size)?; + let b_val = self.memory + .get(ptr.alloc_id)? + .read_scalar(self, b_ptr, ptr_align, b_size)?; Ok(Some(Immediate::ScalarPair(a_val, b_val))) } _ => Ok(None), @@ -345,7 +351,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> mplace: MPlaceTy<'tcx, M::PointerTag>, ) -> EvalResult<'tcx, &str> { let len = mplace.len(self)?; - let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len as u64))?; + let ptr = mplace.ptr.to_ptr()?; + let bytes = self.memory + .get(ptr.alloc_id)? + .read_bytes(self, ptr, Size::from_bytes(len as u64))?; let str = ::std::str::from_utf8(bytes) .map_err(|err| EvalErrorKind::ValidationFailure(err.to_string()))?; Ok(str) diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 7ef3dd5f720..e2b6c00ba38 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -718,6 +718,7 @@ where } let ptr = ptr.to_ptr()?; + let tcx = &*self.tcx; // FIXME: We should check that there are dest.layout.size many bytes available in // memory. The code below is not sufficient, with enough padding it might not // cover all the bytes! @@ -729,8 +730,8 @@ where dest.layout) } - self.memory.write_scalar( - ptr, ptr_align.min(dest.layout.align.abi), scalar, dest.layout.size + self.memory.get_mut(ptr.alloc_id)?.write_scalar( + tcx, ptr, ptr_align.min(dest.layout.align.abi), scalar, dest.layout.size ) } Immediate::ScalarPair(a_val, b_val) => { @@ -742,14 +743,18 @@ where let (a_size, b_size) = (a.size(self), b.size(self)); let (a_align, b_align) = (a.align(self).abi, b.align(self).abi); let b_offset = a_size.align_to(b_align); - let b_ptr = ptr.offset(b_offset, self)?.into(); + let b_ptr = ptr.offset(b_offset, self)?; // It is tempting to verify `b_offset` against `layout.fields.offset(1)`, // but that does not work: We could be a newtype around a pair, then the // fields do not match the `ScalarPair` components. - self.memory.write_scalar(ptr, ptr_align.min(a_align), a_val, a_size)?; - self.memory.write_scalar(b_ptr, ptr_align.min(b_align), b_val, b_size) + self.memory + .get_mut(ptr.alloc_id)? + .write_scalar(tcx, ptr, ptr_align.min(a_align), a_val, a_size)?; + self.memory + .get_mut(b_ptr.alloc_id)? + .write_scalar(tcx, b_ptr, ptr_align.min(b_align), b_val, b_size) } } } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index fd17a4a7129..9e59611125d 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -404,7 +404,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let ptr_align = self.tcx.data_layout.pointer_align.abi; let ptr = self.deref_operand(args[0])?; let vtable = ptr.vtable()?; - let fn_ptr = self.memory.read_ptr_sized( + let fn_ptr = self.memory.get(vtable.alloc_id)?.read_ptr_sized( + self, vtable.offset(ptr_size * (idx as u64 + 3), self)?, ptr_align )?.to_ptr()?; diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index f11fd45b753..8e39574c01e 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -55,23 +55,31 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ptr_align, MemoryKind::Vtable, )?.with_default_tag(); + let tcx = &*self.tcx; - let drop = ::monomorphize::resolve_drop_in_place(*self.tcx, ty); + let drop = ::monomorphize::resolve_drop_in_place(*tcx, ty); let drop = self.memory.create_fn_alloc(drop).with_default_tag(); - self.memory.write_ptr_sized(vtable, ptr_align, Scalar::Ptr(drop).into())?; + self.memory + .get_mut(vtable.alloc_id)? + .write_ptr_sized(tcx, vtable, ptr_align, Scalar::Ptr(drop).into())?; let size_ptr = vtable.offset(ptr_size, self)?; - self.memory.write_ptr_sized(size_ptr, ptr_align, Scalar::from_uint(size, ptr_size).into())?; + self.memory + .get_mut(size_ptr.alloc_id)? + .write_ptr_sized(tcx, size_ptr, ptr_align, Scalar::from_uint(size, ptr_size).into())?; let align_ptr = vtable.offset(ptr_size * 2, self)?; - self.memory.write_ptr_sized(align_ptr, ptr_align, - Scalar::from_uint(align, ptr_size).into())?; + self.memory + .get_mut(align_ptr.alloc_id)? + .write_ptr_sized(tcx, align_ptr, ptr_align, Scalar::from_uint(align, ptr_size).into())?; for (i, method) in methods.iter().enumerate() { if let Some((def_id, substs)) = *method { let instance = self.resolve(def_id, substs)?; let fn_ptr = self.memory.create_fn_alloc(instance).with_default_tag(); let method_ptr = vtable.offset(ptr_size * (3 + i as u64), self)?; - self.memory.write_ptr_sized(method_ptr, ptr_align, Scalar::Ptr(fn_ptr).into())?; + self.memory + .get_mut(method_ptr.alloc_id)? + .write_ptr_sized(tcx, method_ptr, ptr_align, Scalar::Ptr(fn_ptr).into())?; } } @@ -88,7 +96,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ) -> EvalResult<'tcx, (ty::Instance<'tcx>, ty::Ty<'tcx>)> { // we don't care about the pointee type, we just want a pointer let pointer_align = self.tcx.data_layout.pointer_align.abi; - let drop_fn = self.memory.read_ptr_sized(vtable, pointer_align)?.to_ptr()?; + let drop_fn = self.memory + .get(vtable.alloc_id)? + .read_ptr_sized(self, vtable, pointer_align)? + .to_ptr()?; let drop_instance = self.memory.get_fn(drop_fn)?; trace!("Found drop fn: {:?}", drop_instance); let fn_sig = drop_instance.ty(*self.tcx).fn_sig(*self.tcx); @@ -104,9 +115,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ) -> EvalResult<'tcx, (Size, Align)> { let pointer_size = self.pointer_size(); let pointer_align = self.tcx.data_layout.pointer_align.abi; - let size = self.memory.read_ptr_sized(vtable.offset(pointer_size, self)?,pointer_align)? + let alloc = self.memory.get(vtable.alloc_id)?; + let size = alloc.read_ptr_sized(self, vtable.offset(pointer_size, self)?, pointer_align)? .to_bits(pointer_size)? as u64; - let align = self.memory.read_ptr_sized( + let align = alloc.read_ptr_sized( + self, vtable.offset(pointer_size * 2, self)?, pointer_align )?.to_bits(pointer_size)? as u64; diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 6d1cacfa147..b3a82cd7023 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -21,7 +21,7 @@ use rustc::mir::interpret::{ }; use super::{ - OpTy, MPlaceTy, Machine, EvalContext, ValueVisitor + OpTy, MPlaceTy, Machine, EvalContext, ValueVisitor, Operand, }; macro_rules! validation_failure { @@ -396,7 +396,9 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> // Maintain the invariant that the place we are checking is // already verified to be in-bounds. try_validation!( - self.ecx.memory.check_bounds(ptr, size, InboundsCheck::Live), + self.ecx.memory + .get(ptr.alloc_id)? + .check_bounds(self.ecx, ptr, size), "dangling (not entirely in bounds) reference", self.path); } // Check if we have encountered this pointer+layout combination @@ -520,12 +522,14 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> _ => false, } } => { - let mplace = if op.layout.is_zst() { + let mplace = match *op { // it's a ZST, the memory content cannot matter - MPlaceTy::dangling(op.layout, self.ecx) - } else { - // non-ZST array/slice/str cannot be immediate - op.to_mem_place() + Operand::Immediate(_) if op.layout.is_zst() => + // invent an aligned mplace + MPlaceTy::dangling(op.layout, self.ecx), + // FIXME: what about single element arrays? They can be Scalar layout I think + Operand::Immediate(_) => bug!("non-ZST array/slice cannot be immediate"), + Operand::Indirect(_) => op.to_mem_place(), }; // This is the length of the array/slice. let len = mplace.len(self.ecx)?; @@ -534,6 +538,11 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> // This is the size in bytes of the whole array. let size = ty_size * len; + if op.layout.is_zst() { + return self.ecx.memory.check_align(mplace.ptr, op.layout.align); + } + let ptr = mplace.ptr.to_ptr()?; + // NOTE: Keep this in sync with the handling of integer and float // types above, in `visit_primitive`. // In run-time mode, we accept pointers in here. This is actually more @@ -543,8 +552,9 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> // to reject those pointers, we just do not have the machinery to // talk about parts of a pointer. // We also accept undef, for consistency with the type-based checks. - match self.ecx.memory.check_bytes( - mplace.ptr, + match self.ecx.memory.get(ptr.alloc_id)?.check_bytes( + self.ecx, + ptr, size, /*allow_ptr_and_undef*/!self.const_mode, ) { From 3a0e8254b06c8a9c8e4b775a18524797f1e3d44c Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 13 Nov 2018 09:44:59 +0100 Subject: [PATCH 0205/1984] Remove unnecessary `Result` (function always returned `Ok`) --- src/librustc/mir/interpret/allocation.rs | 12 ++++++------ src/librustc_mir/interpret/memory.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 6ef7a5a266d..42bcd3a9027 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -406,12 +406,12 @@ impl<'tcx, Tag: Copy, Extra> Allocation { cx: &impl HasDataLayout, ptr: Pointer, size: Size, - ) -> EvalResult<'tcx, &[(Size, (Tag, AllocId))]> { + ) -> &[(Size, (Tag, AllocId))] { // We have to go back `pointer_size - 1` bytes, as that one would still overlap with // the beginning of this range. let start = ptr.offset.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1); let end = ptr.offset + size; // this does overflow checking - Ok(self.relocations.range(Size::from_bytes(start)..end)) + self.relocations.range(Size::from_bytes(start)..end) } /// Check that there ar eno relocations overlapping with the given range. @@ -422,10 +422,10 @@ impl<'tcx, Tag: Copy, Extra> Allocation { ptr: Pointer, size: Size, ) -> EvalResult<'tcx> { - if self.relocations(cx, ptr, size)?.len() != 0 { - err!(ReadPointerAsBytes) - } else { + if self.relocations(cx, ptr, size).is_empty() { Ok(()) + } else { + err!(ReadPointerAsBytes) } } @@ -444,7 +444,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // Find the start and end of the given range and its outermost relocations. let (first, last) = { // Find all relocations overlapping the given range. - let relocations = self.relocations(cx, ptr, size)?; + let relocations = self.relocations(cx, ptr, size); if relocations.is_empty() { return Ok(()); } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 3119d9ed0ff..896a7a25b5d 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -655,7 +655,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // (`get_bytes_with_undef_and_ptr` below checks that there are no // relocations overlapping the edges; those would not be handled correctly). let relocations = { - let relocations = self.get(src.alloc_id)?.relocations(self, src, size)?; + let relocations = self.get(src.alloc_id)?.relocations(self, src, size); let mut new_relocations = Vec::with_capacity(relocations.len() * (length as usize)); for i in 0..length { new_relocations.extend( From a835555474c87def84099df412816d5edfa2b9cb Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 13 Nov 2018 10:19:12 +0100 Subject: [PATCH 0206/1984] Make zst accesses in allocations take the regular path. Speeding up zst accesses should be done on a higher level. --- src/librustc/mir/interpret/allocation.rs | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 42bcd3a9027..ba2755b29f0 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -116,12 +116,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { size: Size, allow_ptr_and_undef: bool, ) -> EvalResult<'tcx> { - // Empty accesses don't need to be valid pointers, but they should still be non-NULL let align = Align::from_bytes(1).unwrap(); - if size.bytes() == 0 { - self.check_align(ptr, align)?; - return Ok(()); - } // Check bounds, align and relocations on the edges self.get_bytes_with_undef_and_ptr(cx, ptr, size, align)?; // Check undef and ptr @@ -138,12 +133,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { ptr: Pointer, size: Size, ) -> EvalResult<'tcx, &[u8]> { - // Empty accesses don't need to be valid pointers, but they should still be non-NULL let align = Align::from_bytes(1).unwrap(); - if size.bytes() == 0 { - self.check_align(ptr, align)?; - return Ok(&[]); - } self.get_bytes(cx, ptr, size, align) } @@ -153,12 +143,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { ptr: Pointer, src: &[u8], ) -> EvalResult<'tcx> { - // Empty accesses don't need to be valid pointers, but they should still be non-NULL let align = Align::from_bytes(1).unwrap(); - if src.is_empty() { - self.check_align(ptr, align)?; - return Ok(()); - } let bytes = self.get_bytes_mut( cx, ptr, Size::from_bytes(src.len() as u64), align, )?; @@ -173,12 +158,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { val: u8, count: Size ) -> EvalResult<'tcx> { - // Empty accesses don't need to be valid pointers, but they should still be non-NULL let align = Align::from_bytes(1).unwrap(); - if count.bytes() == 0 { - self.check_align(ptr, align)?; - return Ok(()); - } let bytes = self.get_bytes_mut(cx, ptr, count, align)?; for b in bytes { *b = val; @@ -329,7 +309,6 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { align: Align, check_defined_and_ptr: bool, ) -> EvalResult<'tcx, &[u8]> { - assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); self.check_align(ptr.into(), align)?; self.check_bounds(cx, ptr, size)?; From df1ed0c2a68d0a38d98434b734ed042f7b976e5e Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 13 Nov 2018 14:32:39 +0100 Subject: [PATCH 0207/1984] Make a method that doesn't need `Self` a free function instead --- src/librustc/mir/interpret/allocation.rs | 35 ++++++++++++------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index ba2755b29f0..bafa32df848 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -176,7 +176,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { ) -> EvalResult<'tcx, ScalarMaybeUndef> { // get_bytes_unchecked tests alignment and relocation edges let bytes = self.get_bytes_with_undef_and_ptr( - cx, ptr, size, ptr_align.min(self.int_align(cx, size)) + cx, ptr, size, ptr_align.min(int_align(cx, size)) )?; // Undef check happens *after* we established that the alignment is correct. // We must not return Ok() for unaligned pointers! @@ -272,24 +272,23 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { let ptr_size = cx.data_layout().pointer_size; self.write_scalar(cx, ptr.into(), ptr_align, val, ptr_size) } +} - fn int_align( - &self, - cx: &impl HasDataLayout, - size: Size, - ) -> Align { - // We assume pointer-sized integers have the same alignment as pointers. - // We also assume signed and unsigned integers of the same size have the same alignment. - let ity = match size.bytes() { - 1 => layout::I8, - 2 => layout::I16, - 4 => layout::I32, - 8 => layout::I64, - 16 => layout::I128, - _ => bug!("bad integer size: {}", size.bytes()), - }; - ity.align(cx).abi - } +fn int_align( + cx: &impl HasDataLayout, + size: Size, +) -> Align { + // We assume pointer-sized integers have the same alignment as pointers. + // We also assume signed and unsigned integers of the same size have the same alignment. + let ity = match size.bytes() { + 1 => layout::I8, + 2 => layout::I16, + 4 => layout::I32, + 8 => layout::I64, + 16 => layout::I128, + _ => bug!("bad integer size: {}", size.bytes()), + }; + ity.align(cx).abi } /// Byte accessors From 20dee47a66a802c0e7f0b8884632592ad9311357 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 13 Nov 2018 14:54:00 +0100 Subject: [PATCH 0208/1984] Add regression test for integral pointers in zst str slice fat pointers --- src/test/ui/consts/int_ptr_for_zst_slices.rs | 3 +++ .../ui/consts/int_ptr_for_zst_slices.stderr | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/test/ui/consts/int_ptr_for_zst_slices.rs create mode 100644 src/test/ui/consts/int_ptr_for_zst_slices.stderr diff --git a/src/test/ui/consts/int_ptr_for_zst_slices.rs b/src/test/ui/consts/int_ptr_for_zst_slices.rs new file mode 100644 index 00000000000..ece8d3d1505 --- /dev/null +++ b/src/test/ui/consts/int_ptr_for_zst_slices.rs @@ -0,0 +1,3 @@ +const FOO: &str = unsafe { &*(1_usize as *const [u8; 0] as *const [u8] as *const [str]) }; + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/consts/int_ptr_for_zst_slices.stderr b/src/test/ui/consts/int_ptr_for_zst_slices.stderr new file mode 100644 index 00000000000..c7b78d98cc8 --- /dev/null +++ b/src/test/ui/consts/int_ptr_for_zst_slices.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/int_ptr_for_zst_slices.rs:1:28 + | +LL | const FOO: &str = unsafe { &*(1_usize as *const [u8; 0] as *const [u8] as *const [str]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected str, found slice + | + = note: expected type `&'static str` + found type `&[str]` + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/int_ptr_for_zst_slices.rs:1:75 + | +LL | const FOO: &str = unsafe { &*(1_usize as *const [u8; 0] as *const [u8] as *const [str]) }; + | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `str` + = note: to learn more, visit + = note: slice and array elements must have `Sized` type + +error: aborting due to 2 previous errors + +Some errors occurred: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. From cc2f46e55a3fe52affe0dd4aee2ececd75c78031 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 13 Nov 2018 14:55:18 +0100 Subject: [PATCH 0209/1984] Reorder methods in `allocation.rs` --- src/librustc/mir/interpret/allocation.rs | 170 +++++++++++------------ 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index bafa32df848..2e08baa6f51 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -89,6 +89,91 @@ impl<'tcx, Tag, Extra> Allocation { } } +/// Byte accessors +impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { + /// The last argument controls whether we error out when there are undefined + /// or pointer bytes. You should never call this, call `get_bytes` or + /// `get_bytes_with_undef_and_ptr` instead, + /// + /// This function also guarantees that the resulting pointer will remain stable + /// even when new allocations are pushed to the `HashMap`. `copy_repeatedly` relies + /// on that. + fn get_bytes_internal( + &self, + cx: &impl HasDataLayout, + ptr: Pointer, + size: Size, + align: Align, + check_defined_and_ptr: bool, + ) -> EvalResult<'tcx, &[u8]> { + self.check_align(ptr.into(), align)?; + self.check_bounds(cx, ptr, size)?; + + if check_defined_and_ptr { + self.check_defined(ptr, size)?; + self.check_relocations(cx, ptr, size)?; + } else { + // We still don't want relocations on the *edges* + self.check_relocation_edges(cx, ptr, size)?; + } + + AllocationExtra::memory_read(self, ptr, size)?; + + assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); + assert_eq!(size.bytes() as usize as u64, size.bytes()); + let offset = ptr.offset.bytes() as usize; + Ok(&self.bytes[offset..offset + size.bytes() as usize]) + } + + #[inline] + fn get_bytes( + &self, + cx: &impl HasDataLayout, + ptr: Pointer, + size: Size, + align: Align + ) -> EvalResult<'tcx, &[u8]> { + self.get_bytes_internal(cx, ptr, size, align, true) + } + + /// It is the caller's responsibility to handle undefined and pointer bytes. + /// However, this still checks that there are no relocations on the *edges*. + #[inline] + pub fn get_bytes_with_undef_and_ptr( + &self, + cx: &impl HasDataLayout, + ptr: Pointer, + size: Size, + align: Align + ) -> EvalResult<'tcx, &[u8]> { + self.get_bytes_internal(cx, ptr, size, align, false) + } + + /// Just calling this already marks everything as defined and removes relocations, + /// so be sure to actually put data there! + pub fn get_bytes_mut( + &mut self, + cx: &impl HasDataLayout, + ptr: Pointer, + size: Size, + align: Align, + ) -> EvalResult<'tcx, &mut [u8]> { + assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); + self.check_align(ptr.into(), align)?; + self.check_bounds(cx, ptr, size)?; + + self.mark_definedness(ptr, size, true)?; + self.clear_relocations(cx, ptr, size)?; + + AllocationExtra::memory_written(self, ptr, size)?; + + assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); + assert_eq!(size.bytes() as usize as u64, size.bytes()); + let offset = ptr.offset.bytes() as usize; + Ok(&mut self.bytes[offset..offset + size.bytes() as usize]) + } +} + /// Reading and writing impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { pub fn read_c_str( @@ -291,91 +376,6 @@ fn int_align( ity.align(cx).abi } -/// Byte accessors -impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { - /// The last argument controls whether we error out when there are undefined - /// or pointer bytes. You should never call this, call `get_bytes` or - /// `get_bytes_with_undef_and_ptr` instead, - /// - /// This function also guarantees that the resulting pointer will remain stable - /// even when new allocations are pushed to the `HashMap`. `copy_repeatedly` relies - /// on that. - fn get_bytes_internal( - &self, - cx: &impl HasDataLayout, - ptr: Pointer, - size: Size, - align: Align, - check_defined_and_ptr: bool, - ) -> EvalResult<'tcx, &[u8]> { - self.check_align(ptr.into(), align)?; - self.check_bounds(cx, ptr, size)?; - - if check_defined_and_ptr { - self.check_defined(ptr, size)?; - self.check_relocations(cx, ptr, size)?; - } else { - // We still don't want relocations on the *edges* - self.check_relocation_edges(cx, ptr, size)?; - } - - AllocationExtra::memory_read(self, ptr, size)?; - - assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); - assert_eq!(size.bytes() as usize as u64, size.bytes()); - let offset = ptr.offset.bytes() as usize; - Ok(&self.bytes[offset..offset + size.bytes() as usize]) - } - - #[inline] - fn get_bytes( - &self, - cx: &impl HasDataLayout, - ptr: Pointer, - size: Size, - align: Align - ) -> EvalResult<'tcx, &[u8]> { - self.get_bytes_internal(cx, ptr, size, align, true) - } - - /// It is the caller's responsibility to handle undefined and pointer bytes. - /// However, this still checks that there are no relocations on the *edges*. - #[inline] - pub fn get_bytes_with_undef_and_ptr( - &self, - cx: &impl HasDataLayout, - ptr: Pointer, - size: Size, - align: Align - ) -> EvalResult<'tcx, &[u8]> { - self.get_bytes_internal(cx, ptr, size, align, false) - } - - /// Just calling this already marks everything as defined and removes relocations, - /// so be sure to actually put data there! - pub fn get_bytes_mut( - &mut self, - cx: &impl HasDataLayout, - ptr: Pointer, - size: Size, - align: Align, - ) -> EvalResult<'tcx, &mut [u8]> { - assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); - self.check_align(ptr.into(), align)?; - self.check_bounds(cx, ptr, size)?; - - self.mark_definedness(ptr, size, true)?; - self.clear_relocations(cx, ptr, size)?; - - AllocationExtra::memory_written(self, ptr, size)?; - - assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); - assert_eq!(size.bytes() as usize as u64, size.bytes()); - let offset = ptr.offset.bytes() as usize; - Ok(&mut self.bytes[offset..offset + size.bytes() as usize]) - } -} - /// Relocations impl<'tcx, Tag: Copy, Extra> Allocation { /// Return all relocations overlapping with the given ptr-offset pair. From ebf03363f2d2385bc2248549cd93fca42779699a Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 13 Nov 2018 15:36:05 +0100 Subject: [PATCH 0210/1984] Properly test for int pointers in fat pointers to str slices of zero chars --- src/test/ui/consts/int_ptr_for_zst_slices.rs | 7 +++-- .../ui/consts/int_ptr_for_zst_slices.stderr | 26 +++++-------------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/test/ui/consts/int_ptr_for_zst_slices.rs b/src/test/ui/consts/int_ptr_for_zst_slices.rs index ece8d3d1505..809cc15be0c 100644 --- a/src/test/ui/consts/int_ptr_for_zst_slices.rs +++ b/src/test/ui/consts/int_ptr_for_zst_slices.rs @@ -1,3 +1,6 @@ -const FOO: &str = unsafe { &*(1_usize as *const [u8; 0] as *const [u8] as *const [str]) }; +#![feature(const_raw_ptr_deref)] -fn main() {} \ No newline at end of file +const FOO: &str = unsafe { &*(1_usize as *const [u8; 0] as *const [u8] as *const str) }; +//~^ ERROR it is undefined behaviour to use this value + +fn main() {} diff --git a/src/test/ui/consts/int_ptr_for_zst_slices.stderr b/src/test/ui/consts/int_ptr_for_zst_slices.stderr index c7b78d98cc8..437e6952e74 100644 --- a/src/test/ui/consts/int_ptr_for_zst_slices.stderr +++ b/src/test/ui/consts/int_ptr_for_zst_slices.stderr @@ -1,23 +1,11 @@ -error[E0308]: mismatched types - --> $DIR/int_ptr_for_zst_slices.rs:1:28 +error[E0080]: it is undefined behavior to use this value + --> $DIR/int_ptr_for_zst_slices.rs:3:1 | -LL | const FOO: &str = unsafe { &*(1_usize as *const [u8; 0] as *const [u8] as *const [str]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected str, found slice +LL | const FOO: &str = unsafe { &*(1_usize as *const [u8; 0] as *const [u8] as *const str) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . | - = note: expected type `&'static str` - found type `&[str]` + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior -error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/int_ptr_for_zst_slices.rs:1:75 - | -LL | const FOO: &str = unsafe { &*(1_usize as *const [u8; 0] as *const [u8] as *const [str]) }; - | ^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `std::marker::Sized` is not implemented for `str` - = note: to learn more, visit - = note: slice and array elements must have `Sized` type - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0080`. From ef332959dc42f25da567ae9a345ad395a19234a1 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 13 Nov 2018 16:13:51 +0100 Subject: [PATCH 0211/1984] Reintroduce zst-slice reading `read_bytes` method on `Memory` --- src/librustc_mir/interpret/memory.rs | 16 ++++++++++++++++ src/librustc_mir/interpret/operand.rs | 5 +---- src/test/ui/consts/int_ptr_for_zst_slices.rs | 3 ++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 896a7a25b5d..b468943cbf0 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -567,6 +567,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } } +/// Byte Accessors +impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { + pub fn read_bytes( + &self, + ptr: Scalar, + size: Size, + ) -> EvalResult<'tcx, &[u8]> { + if size.bytes() == 0 { + Ok(&[]) + } else { + let ptr = ptr.to_ptr()?; + self.get(ptr.alloc_id)?.read_bytes(self, ptr, size) + } + } +} + /// Interning (for CTFE) impl<'a, 'mir, 'tcx, M> Memory<'a, 'mir, 'tcx, M> where diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 3f5f0ebed72..0fb5b59e442 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -351,10 +351,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> mplace: MPlaceTy<'tcx, M::PointerTag>, ) -> EvalResult<'tcx, &str> { let len = mplace.len(self)?; - let ptr = mplace.ptr.to_ptr()?; - let bytes = self.memory - .get(ptr.alloc_id)? - .read_bytes(self, ptr, Size::from_bytes(len as u64))?; + let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len as u64))?; let str = ::std::str::from_utf8(bytes) .map_err(|err| EvalErrorKind::ValidationFailure(err.to_string()))?; Ok(str) diff --git a/src/test/ui/consts/int_ptr_for_zst_slices.rs b/src/test/ui/consts/int_ptr_for_zst_slices.rs index 809cc15be0c..afa2c6a5b9e 100644 --- a/src/test/ui/consts/int_ptr_for_zst_slices.rs +++ b/src/test/ui/consts/int_ptr_for_zst_slices.rs @@ -1,6 +1,7 @@ +// compile-pass + #![feature(const_raw_ptr_deref)] const FOO: &str = unsafe { &*(1_usize as *const [u8; 0] as *const [u8] as *const str) }; -//~^ ERROR it is undefined behaviour to use this value fn main() {} From 87bd5d13d8a175a0be82fe2b1db5588036c4bdb6 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 13 Nov 2018 17:23:26 +0100 Subject: [PATCH 0212/1984] Remove stderr file, because the test passes now --- src/test/ui/consts/int_ptr_for_zst_slices.stderr | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 src/test/ui/consts/int_ptr_for_zst_slices.stderr diff --git a/src/test/ui/consts/int_ptr_for_zst_slices.stderr b/src/test/ui/consts/int_ptr_for_zst_slices.stderr deleted file mode 100644 index 437e6952e74..00000000000 --- a/src/test/ui/consts/int_ptr_for_zst_slices.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0080]: it is undefined behavior to use this value - --> $DIR/int_ptr_for_zst_slices.rs:3:1 - | -LL | const FOO: &str = unsafe { &*(1_usize as *const [u8; 0] as *const [u8] as *const str) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0080`. From 65b702c6b108dfa5e2c3fa891d4f96755293ddb3 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 14 Nov 2018 10:56:09 +0100 Subject: [PATCH 0213/1984] Update miri submodule --- Cargo.lock | 8 ++++---- src/tools/miri | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f7d5a1a507b..dc9296b81e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -306,7 +306,7 @@ dependencies = [ "clippy-mini-macro-test 0.2.0", "clippy_dev 0.0.1", "clippy_lints 0.0.212", - "compiletest_rs 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "compiletest_rs 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -423,7 +423,7 @@ dependencies = [ [[package]] name = "compiletest_rs" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1315,7 +1315,7 @@ dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "compiletest_rs 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "compiletest_rs 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "vergen 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3274,7 +3274,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" -"checksum compiletest_rs 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "75e809f56d6aa9575b67924b0af686c4f4c1380314f47947e235e9ff7fa94bed" +"checksum compiletest_rs 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "89747fe073b7838343bd2c2445e7a7c2e0d415598f8925f0fa9205b9cdfc48cb" "checksum core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cc3532ec724375c7cb7ff0a097b714fde180bb1f6ed2ab27cfcd99ffca873cd2" "checksum core-foundation-sys 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a3fb15cdbdd9cf8b82d97d0296bb5cd3631bba58d6e31650a002a8e7fb5721f9" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" diff --git a/src/tools/miri b/src/tools/miri index bbb1d80703f..06758c48bd7 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit bbb1d80703f272a5592ceeb3832a489776512251 +Subproject commit 06758c48bd7a77bb5aa43fc50cf344540ba5afef From b820cc79a93a8867b1fe51ab628663671843a4ed Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 14 Nov 2018 11:45:10 +0100 Subject: [PATCH 0214/1984] Clean up array/slice of primitive validation --- src/librustc_mir/interpret/validity.rs | 23 ++++++++----------- src/test/ui/consts/validate_never_arrays.rs | 5 ++++ .../ui/consts/validate_never_arrays.stderr | 11 +++++++++ 3 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/consts/validate_never_arrays.rs create mode 100644 src/test/ui/consts/validate_never_arrays.stderr diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index b3a82cd7023..4b9ded4c17e 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -21,7 +21,7 @@ use rustc::mir::interpret::{ }; use super::{ - OpTy, MPlaceTy, Machine, EvalContext, ValueVisitor, Operand, + OpTy, Machine, EvalContext, ValueVisitor, }; macro_rules! validation_failure { @@ -522,25 +522,22 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> _ => false, } } => { - let mplace = match *op { - // it's a ZST, the memory content cannot matter - Operand::Immediate(_) if op.layout.is_zst() => - // invent an aligned mplace - MPlaceTy::dangling(op.layout, self.ecx), - // FIXME: what about single element arrays? They can be Scalar layout I think - Operand::Immediate(_) => bug!("non-ZST array/slice cannot be immediate"), - Operand::Indirect(_) => op.to_mem_place(), - }; + if op.layout.is_zst() { + return Ok(()); + } + // non-ZST array cannot be immediate, slices are never immediate + let mplace = op.to_mem_place(); // This is the length of the array/slice. let len = mplace.len(self.ecx)?; + // zero length slices have nothing to be checked + if len == 0 { + return Ok(()); + } // This is the element type size. let ty_size = self.ecx.layout_of(tys)?.size; // This is the size in bytes of the whole array. let size = ty_size * len; - if op.layout.is_zst() { - return self.ecx.memory.check_align(mplace.ptr, op.layout.align); - } let ptr = mplace.ptr.to_ptr()?; // NOTE: Keep this in sync with the handling of integer and float diff --git a/src/test/ui/consts/validate_never_arrays.rs b/src/test/ui/consts/validate_never_arrays.rs new file mode 100644 index 00000000000..9610b7b22f1 --- /dev/null +++ b/src/test/ui/consts/validate_never_arrays.rs @@ -0,0 +1,5 @@ +#![feature(const_raw_ptr_deref, never_type)] + +const FOO: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior + +fn main() {} diff --git a/src/test/ui/consts/validate_never_arrays.stderr b/src/test/ui/consts/validate_never_arrays.stderr new file mode 100644 index 00000000000..0b639240bb3 --- /dev/null +++ b/src/test/ui/consts/validate_never_arrays.stderr @@ -0,0 +1,11 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/validate_never_arrays.rs:3:1 + | +LL | const FOO: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .[0] + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. From d3139b9c4157957aa40f212f5d423db4359001a9 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 14 Nov 2018 12:19:56 +0100 Subject: [PATCH 0215/1984] Rebase fallout --- src/librustc_mir/interpret/memory.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index b468943cbf0..c7c6dd12846 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -30,7 +30,7 @@ use syntax::ast::Mutability; use super::{ Pointer, AllocId, Allocation, GlobalId, AllocationExtra, InboundsCheck, EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic, - Machine, AllocMap, MayLeak, ErrorHandled, + Machine, AllocMap, MayLeak, ErrorHandled, AllocationExtra, }; #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] From 1c08ced99589114164f057bc4cd020a6bad48af9 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 14 Nov 2018 13:28:38 +0100 Subject: [PATCH 0216/1984] Explain early abort legality --- src/librustc_mir/interpret/validity.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 4b9ded4c17e..8ce5a0365cf 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -522,6 +522,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> _ => false, } } => { + // bailing out for zsts is ok, since the array element type can only be int/float if op.layout.is_zst() { return Ok(()); } From 8b04b098695951f561ef4eedf33c6fbc63728caa Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 15 Nov 2018 14:43:58 +0100 Subject: [PATCH 0217/1984] Move alignment checks out of `Allocation` --- src/librustc/mir/interpret/allocation.rs | 69 +++++------------------- src/librustc_mir/interpret/memory.rs | 12 ++--- src/librustc_mir/interpret/operand.rs | 11 ++-- src/librustc_mir/interpret/place.rs | 16 +++--- src/librustc_mir/interpret/terminator.rs | 3 +- src/librustc_mir/interpret/traits.rs | 17 +++--- 6 files changed, 43 insertions(+), 85 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 2e08baa6f51..b2c44548805 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -15,7 +15,7 @@ use super::{ truncate, }; -use ty::layout::{self, Size, Align}; +use ty::layout::{Size, Align}; use syntax::ast::Mutability; use std::iter; use mir; @@ -103,10 +103,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { cx: &impl HasDataLayout, ptr: Pointer, size: Size, - align: Align, check_defined_and_ptr: bool, ) -> EvalResult<'tcx, &[u8]> { - self.check_align(ptr.into(), align)?; self.check_bounds(cx, ptr, size)?; if check_defined_and_ptr { @@ -126,14 +124,13 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { } #[inline] - fn get_bytes( + pub fn get_bytes( &self, cx: &impl HasDataLayout, ptr: Pointer, size: Size, - align: Align ) -> EvalResult<'tcx, &[u8]> { - self.get_bytes_internal(cx, ptr, size, align, true) + self.get_bytes_internal(cx, ptr, size, true) } /// It is the caller's responsibility to handle undefined and pointer bytes. @@ -144,9 +141,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { cx: &impl HasDataLayout, ptr: Pointer, size: Size, - align: Align ) -> EvalResult<'tcx, &[u8]> { - self.get_bytes_internal(cx, ptr, size, align, false) + self.get_bytes_internal(cx, ptr, size, false) } /// Just calling this already marks everything as defined and removes relocations, @@ -156,10 +152,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { cx: &impl HasDataLayout, ptr: Pointer, size: Size, - align: Align, ) -> EvalResult<'tcx, &mut [u8]> { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); - self.check_align(ptr.into(), align)?; self.check_bounds(cx, ptr, size)?; self.mark_definedness(ptr, size, true)?; @@ -201,9 +195,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { size: Size, allow_ptr_and_undef: bool, ) -> EvalResult<'tcx> { - let align = Align::from_bytes(1).unwrap(); // Check bounds, align and relocations on the edges - self.get_bytes_with_undef_and_ptr(cx, ptr, size, align)?; + self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; // Check undef and ptr if !allow_ptr_and_undef { self.check_defined(ptr, size)?; @@ -212,26 +205,13 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Ok(()) } - pub fn read_bytes( - &self, - cx: &impl HasDataLayout, - ptr: Pointer, - size: Size, - ) -> EvalResult<'tcx, &[u8]> { - let align = Align::from_bytes(1).unwrap(); - self.get_bytes(cx, ptr, size, align) - } - pub fn write_bytes( &mut self, cx: &impl HasDataLayout, ptr: Pointer, src: &[u8], ) -> EvalResult<'tcx> { - let align = Align::from_bytes(1).unwrap(); - let bytes = self.get_bytes_mut( - cx, ptr, Size::from_bytes(src.len() as u64), align, - )?; + let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64))?; bytes.clone_from_slice(src); Ok(()) } @@ -243,8 +223,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { val: u8, count: Size ) -> EvalResult<'tcx> { - let align = Align::from_bytes(1).unwrap(); - let bytes = self.get_bytes_mut(cx, ptr, count, align)?; + let bytes = self.get_bytes_mut(cx, ptr, count)?; for b in bytes { *b = val; } @@ -256,13 +235,10 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { &self, cx: &impl HasDataLayout, ptr: Pointer, - ptr_align: Align, size: Size ) -> EvalResult<'tcx, ScalarMaybeUndef> { - // get_bytes_unchecked tests alignment and relocation edges - let bytes = self.get_bytes_with_undef_and_ptr( - cx, ptr, size, ptr_align.min(int_align(cx, size)) - )?; + // get_bytes_unchecked tests relocation edges + let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; // Undef check happens *after* we established that the alignment is correct. // We must not return Ok() for unaligned pointers! if self.check_defined(ptr, size).is_err() { @@ -293,9 +269,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { &self, cx: &impl HasDataLayout, ptr: Pointer, - ptr_align: Align ) -> EvalResult<'tcx, ScalarMaybeUndef> { - self.read_scalar(cx, ptr, ptr_align, cx.data_layout().pointer_size) + self.read_scalar(cx, ptr, cx.data_layout().pointer_size) } /// Write a *non-ZST* scalar @@ -303,7 +278,6 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { &mut self, cx: &impl HasDataLayout, ptr: Pointer, - ptr_align: Align, val: ScalarMaybeUndef, type_size: Size, ) -> EvalResult<'tcx> { @@ -327,9 +301,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { }; { - // get_bytes_mut checks alignment let endian = cx.data_layout().endian; - let dst = self.get_bytes_mut(cx, ptr, type_size, ptr_align)?; + let dst = self.get_bytes_mut(cx, ptr, type_size)?; write_target_uint(endian, dst, bytes).unwrap(); } @@ -351,31 +324,13 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { &mut self, cx: &impl HasDataLayout, ptr: Pointer, - ptr_align: Align, val: ScalarMaybeUndef ) -> EvalResult<'tcx> { let ptr_size = cx.data_layout().pointer_size; - self.write_scalar(cx, ptr.into(), ptr_align, val, ptr_size) + self.write_scalar(cx, ptr.into(), val, ptr_size) } } -fn int_align( - cx: &impl HasDataLayout, - size: Size, -) -> Align { - // We assume pointer-sized integers have the same alignment as pointers. - // We also assume signed and unsigned integers of the same size have the same alignment. - let ity = match size.bytes() { - 1 => layout::I8, - 2 => layout::I16, - 4 => layout::I32, - 8 => layout::I64, - 16 => layout::I128, - _ => bug!("bad integer size: {}", size.bytes()), - }; - ity.align(cx).abi -} - /// Relocations impl<'tcx, Tag: Copy, Extra> Allocation { /// Return all relocations overlapping with the given ptr-offset pair. diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index c7c6dd12846..2e47d7e69d9 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -578,7 +578,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok(&[]) } else { let ptr = ptr.to_ptr()?; - self.get(ptr.alloc_id)?.read_bytes(self, ptr, size) + self.get(ptr.alloc_id)?.get_bytes(self, ptr, size) } } } @@ -656,10 +656,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { length: u64, nonoverlapping: bool, ) -> EvalResult<'tcx> { + self.check_align(src, src_align)?; + self.check_align(dest, dest_align)?; if size.bytes() == 0 { // Nothing to do for ZST, other than checking alignment and non-NULLness. - self.check_align(src, src_align)?; - self.check_align(dest, dest_align)?; return Ok(()); } let src = src.to_ptr()?; @@ -689,12 +689,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { let tcx = self.tcx.tcx; - // This also checks alignment, and relocation edges on the src. + // This checks relocation edges on the src. let src_bytes = self.get(src.alloc_id)? - .get_bytes_with_undef_and_ptr(&tcx, src, size, src_align)? + .get_bytes_with_undef_and_ptr(&tcx, src, size)? .as_ptr(); let dest_bytes = self.get_mut(dest.alloc_id)? - .get_bytes_mut(&tcx, dest, size * length, dest_align)? + .get_bytes_mut(&tcx, dest, size * length)? .as_mut_ptr(); // SAFE: The above indexing would have panicked if there weren't at least `size` bytes diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 0fb5b59e442..ba995afddc8 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -275,12 +275,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> return Ok(Some(Immediate::Scalar(Scalar::zst().into()))); } + // check for integer pointers before alignment to report better errors let ptr = ptr.to_ptr()?; + self.memory.check_align(ptr.into(), ptr_align)?; match mplace.layout.abi { layout::Abi::Scalar(..) => { let scalar = self.memory .get(ptr.alloc_id)? - .read_scalar(self, ptr, ptr_align, mplace.layout.size)?; + .read_scalar(self, ptr, mplace.layout.size)?; Ok(Some(Immediate::Scalar(scalar))) } layout::Abi::ScalarPair(ref a, ref b) => { @@ -289,13 +291,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let a_ptr = ptr; let b_offset = a_size.align_to(b.align(self).abi); assert!(b_offset.bytes() > 0); // we later use the offset to test which field to use - let b_ptr = ptr.offset(b_offset, self)?.into(); + let b_ptr = ptr.offset(b_offset, self)?; let a_val = self.memory .get(ptr.alloc_id)? - .read_scalar(self, a_ptr, ptr_align, a_size)?; + .read_scalar(self, a_ptr, a_size)?; + self.memory.check_align(b_ptr.into(), b.align(self))?; let b_val = self.memory .get(ptr.alloc_id)? - .read_scalar(self, b_ptr, ptr_align, b_size)?; + .read_scalar(self, b_ptr, b_size)?; Ok(Some(Immediate::ScalarPair(a_val, b_val))) } _ => Ok(None), diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index e2b6c00ba38..6317cfb94d2 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -713,11 +713,12 @@ where // Nothing to do for ZSTs, other than checking alignment if dest.layout.is_zst() { - self.memory.check_align(ptr, ptr_align)?; - return Ok(()); + return self.memory.check_align(ptr, ptr_align); } + // check for integer pointers before alignment to report better errors let ptr = ptr.to_ptr()?; + self.memory.check_align(ptr.into(), ptr_align)?; let tcx = &*self.tcx; // FIXME: We should check that there are dest.layout.size many bytes available in // memory. The code below is not sufficient, with enough padding it might not @@ -729,9 +730,8 @@ where _ => bug!("write_immediate_to_mplace: invalid Scalar layout: {:#?}", dest.layout) } - self.memory.get_mut(ptr.alloc_id)?.write_scalar( - tcx, ptr, ptr_align.min(dest.layout.align.abi), scalar, dest.layout.size + tcx, ptr, scalar, dest.layout.size ) } Immediate::ScalarPair(a_val, b_val) => { @@ -741,20 +741,22 @@ where dest.layout) }; let (a_size, b_size) = (a.size(self), b.size(self)); - let (a_align, b_align) = (a.align(self).abi, b.align(self).abi); + let b_align = b.align(self).abi; let b_offset = a_size.align_to(b_align); let b_ptr = ptr.offset(b_offset, self)?; + self.memory.check_align(b_ptr.into(), ptr_align.min(b_align))?; + // It is tempting to verify `b_offset` against `layout.fields.offset(1)`, // but that does not work: We could be a newtype around a pair, then the // fields do not match the `ScalarPair` components. self.memory .get_mut(ptr.alloc_id)? - .write_scalar(tcx, ptr, ptr_align.min(a_align), a_val, a_size)?; + .write_scalar(tcx, ptr, a_val, a_size)?; self.memory .get_mut(b_ptr.alloc_id)? - .write_scalar(tcx, b_ptr, ptr_align.min(b_align), b_val, b_size) + .write_scalar(tcx, b_ptr, b_val, b_size) } } } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 9e59611125d..617d204fe10 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -401,13 +401,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // cannot use the shim here, because that will only result in infinite recursion ty::InstanceDef::Virtual(_, idx) => { let ptr_size = self.pointer_size(); - let ptr_align = self.tcx.data_layout.pointer_align.abi; let ptr = self.deref_operand(args[0])?; let vtable = ptr.vtable()?; + self.memory.check_align(vtable.into(), self.tcx.data_layout.pointer_align.abi)?; let fn_ptr = self.memory.get(vtable.alloc_id)?.read_ptr_sized( self, vtable.offset(ptr_size * (idx as u64 + 3), self)?, - ptr_align )?.to_ptr()?; let instance = self.memory.get_fn(fn_ptr)?; diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index 8e39574c01e..37979c8ee66 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -61,16 +61,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let drop = self.memory.create_fn_alloc(drop).with_default_tag(); self.memory .get_mut(vtable.alloc_id)? - .write_ptr_sized(tcx, vtable, ptr_align, Scalar::Ptr(drop).into())?; + .write_ptr_sized(tcx, vtable, Scalar::Ptr(drop).into())?; let size_ptr = vtable.offset(ptr_size, self)?; self.memory .get_mut(size_ptr.alloc_id)? - .write_ptr_sized(tcx, size_ptr, ptr_align, Scalar::from_uint(size, ptr_size).into())?; + .write_ptr_sized(tcx, size_ptr, Scalar::from_uint(size, ptr_size).into())?; let align_ptr = vtable.offset(ptr_size * 2, self)?; self.memory .get_mut(align_ptr.alloc_id)? - .write_ptr_sized(tcx, align_ptr, ptr_align, Scalar::from_uint(align, ptr_size).into())?; + .write_ptr_sized(tcx, align_ptr, Scalar::from_uint(align, ptr_size).into())?; for (i, method) in methods.iter().enumerate() { if let Some((def_id, substs)) = *method { @@ -79,7 +79,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let method_ptr = vtable.offset(ptr_size * (3 + i as u64), self)?; self.memory .get_mut(method_ptr.alloc_id)? - .write_ptr_sized(tcx, method_ptr, ptr_align, Scalar::Ptr(fn_ptr).into())?; + .write_ptr_sized(tcx, method_ptr, Scalar::Ptr(fn_ptr).into())?; } } @@ -95,10 +95,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> vtable: Pointer, ) -> EvalResult<'tcx, (ty::Instance<'tcx>, ty::Ty<'tcx>)> { // we don't care about the pointee type, we just want a pointer - let pointer_align = self.tcx.data_layout.pointer_align.abi; + self.memory.check_align(vtable.into(), self.tcx.data_layout.pointer_align.abi)?; let drop_fn = self.memory .get(vtable.alloc_id)? - .read_ptr_sized(self, vtable, pointer_align)? + .read_ptr_sized(self, vtable)? .to_ptr()?; let drop_instance = self.memory.get_fn(drop_fn)?; trace!("Found drop fn: {:?}", drop_instance); @@ -114,14 +114,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> vtable: Pointer, ) -> EvalResult<'tcx, (Size, Align)> { let pointer_size = self.pointer_size(); - let pointer_align = self.tcx.data_layout.pointer_align.abi; + self.memory.check_align(vtable.into(), self.tcx.data_layout.pointer_align.abi)?; let alloc = self.memory.get(vtable.alloc_id)?; - let size = alloc.read_ptr_sized(self, vtable.offset(pointer_size, self)?, pointer_align)? + let size = alloc.read_ptr_sized(self, vtable.offset(pointer_size, self)?)? .to_bits(pointer_size)? as u64; let align = alloc.read_ptr_sized( self, vtable.offset(pointer_size * 2, self)?, - pointer_align )?.to_bits(pointer_size)? as u64; Ok((Size::from_bytes(size), Align::from_bytes(align).unwrap())) } From 9d57adf2ba57420903b4c9b4dbb492c3fcf691b8 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 15 Nov 2018 14:48:34 +0100 Subject: [PATCH 0218/1984] Explain {read,write}_scalar failure to cope with zsts --- src/librustc/mir/interpret/allocation.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index b2c44548805..2ecd5eb5a62 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -231,6 +231,11 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { } /// Read a *non-ZST* scalar + /// + /// zsts can't be read out of two reasons: + /// * byteorder cannot work with zero element buffers + /// * in oder to obtain a `Pointer` we need to check for ZSTness anyway due to integer pointers + /// being valid for ZSTs pub fn read_scalar( &self, cx: &impl HasDataLayout, @@ -274,6 +279,11 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { } /// Write a *non-ZST* scalar + /// + /// zsts can't be read out of two reasons: + /// * byteorder cannot work with zero element buffers + /// * in oder to obtain a `Pointer` we need to check for ZSTness anyway due to integer pointers + /// being valid for ZSTs pub fn write_scalar( &mut self, cx: &impl HasDataLayout, From 927c5aab47c624fe9f4cf02289a2acccd425432c Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 15 Nov 2018 17:47:11 +0100 Subject: [PATCH 0219/1984] Use correct alignment for fat pointer extra part --- src/librustc_mir/interpret/operand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index ba995afddc8..61c3c6f24ff 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -295,7 +295,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let a_val = self.memory .get(ptr.alloc_id)? .read_scalar(self, a_ptr, a_size)?; - self.memory.check_align(b_ptr.into(), b.align(self))?; + self.memory.check_align(b_ptr.into(), b.align(self).min(ptr_align))?; let b_val = self.memory .get(ptr.alloc_id)? .read_scalar(self, b_ptr, b_size)?; From 9b8e82ad242ba438b0db983248c59281b4355891 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 15 Nov 2018 18:05:15 +0100 Subject: [PATCH 0220/1984] Use correct alignment checks for scalars and zsts, too --- src/librustc_mir/interpret/operand.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 61c3c6f24ff..4ec01b6ca10 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -271,13 +271,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> if mplace.layout.is_zst() { // Not all ZSTs have a layout we would handle below, so just short-circuit them // all here. - self.memory.check_align(ptr, ptr_align)?; + self.memory.check_align(ptr, ptr_align.min(mplace.layout.align))?; return Ok(Some(Immediate::Scalar(Scalar::zst().into()))); } // check for integer pointers before alignment to report better errors let ptr = ptr.to_ptr()?; - self.memory.check_align(ptr.into(), ptr_align)?; + self.memory.check_align(ptr.into(), ptr_align.min(mplace.layout.align))?; match mplace.layout.abi { layout::Abi::Scalar(..) => { let scalar = self.memory From 10102d1f0aa0e7e612ea2a51d5329af928b07f03 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 16 Nov 2018 11:16:34 +0100 Subject: [PATCH 0221/1984] comment nit Co-Authored-By: oli-obk --- src/librustc_mir/interpret/memory.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 2e47d7e69d9..1cb9543b366 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -659,7 +659,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { self.check_align(src, src_align)?; self.check_align(dest, dest_align)?; if size.bytes() == 0 { - // Nothing to do for ZST, other than checking alignment and non-NULLness. + // Nothing to do for ZST, other than checking alignment and non-NULLness which already happened. return Ok(()); } let src = src.to_ptr()?; From a5ef2d1b54c833783a64a98d5d585bb44218497a Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 16 Nov 2018 11:46:58 +0100 Subject: [PATCH 0222/1984] Array and slice projections need to update the place alignment --- src/librustc_mir/interpret/operand.rs | 7 ++++--- src/librustc_mir/interpret/place.rs | 12 +++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 4ec01b6ca10..9588a931c4a 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -271,13 +271,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> if mplace.layout.is_zst() { // Not all ZSTs have a layout we would handle below, so just short-circuit them // all here. - self.memory.check_align(ptr, ptr_align.min(mplace.layout.align))?; + self.memory.check_align(ptr, ptr_align)?; return Ok(Some(Immediate::Scalar(Scalar::zst().into()))); } // check for integer pointers before alignment to report better errors let ptr = ptr.to_ptr()?; - self.memory.check_align(ptr.into(), ptr_align.min(mplace.layout.align))?; + self.memory.check_align(ptr.into(), ptr_align)?; match mplace.layout.abi { layout::Abi::Scalar(..) => { let scalar = self.memory @@ -295,7 +295,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let a_val = self.memory .get(ptr.alloc_id)? .read_scalar(self, a_ptr, a_size)?; - self.memory.check_align(b_ptr.into(), b.align(self).min(ptr_align))?; + let b_align = ptr_align.restrict_for_offset(b_offset); + self.memory.check_align(b_ptr.into(), b_align)?; let b_val = self.memory .get(ptr.alloc_id)? .read_scalar(self, b_ptr, b_size)?; diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 6317cfb94d2..d93aca7f4e1 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -393,8 +393,9 @@ where let dl = &self.tcx.data_layout; Ok((0..len).map(move |i| { let ptr = base.ptr.ptr_offset(i * stride, dl)?; + let align = base.align.restrict_for_offset(i * stride); Ok(MPlaceTy { - mplace: MemPlace { ptr, align: base.align, meta: None }, + mplace: MemPlace { ptr, align, meta: None }, layout }) })) @@ -417,6 +418,7 @@ where _ => bug!("Unexpected layout of index access: {:#?}", base.layout), }; let ptr = base.ptr.ptr_offset(from_offset, self)?; + let align = base.align.restrict_for_offset(from_offset); // Compute meta and new layout let inner_len = len - to - from; @@ -435,7 +437,7 @@ where let layout = self.layout_of(ty)?; Ok(MPlaceTy { - mplace: MemPlace { ptr, align: base.align, meta }, + mplace: MemPlace { ptr, align, meta }, layout }) } @@ -741,11 +743,11 @@ where dest.layout) }; let (a_size, b_size) = (a.size(self), b.size(self)); - let b_align = b.align(self).abi; - let b_offset = a_size.align_to(b_align); + let b_offset = a_size.align_to(b.align(self).abi); + let b_align = ptr_align.restrict_for_offset(b_offset); let b_ptr = ptr.offset(b_offset, self)?; - self.memory.check_align(b_ptr.into(), ptr_align.min(b_align))?; + self.memory.check_align(b_ptr.into(), b_align)?; // It is tempting to verify `b_offset` against `layout.fields.offset(1)`, // but that does not work: We could be a newtype around a pair, then the From cb8fa335721285809c5930cd0fded35899a05064 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 16 Nov 2018 11:48:48 +0100 Subject: [PATCH 0223/1984] tidy --- src/librustc_mir/interpret/memory.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 1cb9543b366..42500237645 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -659,7 +659,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { self.check_align(src, src_align)?; self.check_align(dest, dest_align)?; if size.bytes() == 0 { - // Nothing to do for ZST, other than checking alignment and non-NULLness which already happened. + // Nothing to do for ZST, other than checking alignment and + // non-NULLness which already happened. return Ok(()); } let src = src.to_ptr()?; From 972d798881cb470aa7a75b9ed7fa6c37117492e0 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 16 Nov 2018 16:25:15 +0100 Subject: [PATCH 0224/1984] Document `Allocation` --- src/librustc/mir/interpret/allocation.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 2ecd5eb5a62..296c2e2dd6b 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -170,6 +170,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Reading and writing impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { + /// Reads bytes until a `0` is encountered. Will error if the end of the allocation is reached + /// before a `0` is found. pub fn read_c_str( &self, cx: &impl HasDataLayout, @@ -188,6 +190,9 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { } } + /// Validates that `ptr.offset` and `ptr.offset + size` do not point to the middle of a + /// relocation. If `allow_ptr_and_undef` is `false`, also enforces that the memory in the + /// given range contains neither relocations nor undef bytes. pub fn check_bytes( &self, cx: &impl HasDataLayout, @@ -195,7 +200,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { size: Size, allow_ptr_and_undef: bool, ) -> EvalResult<'tcx> { - // Check bounds, align and relocations on the edges + // Check bounds and relocations on the edges self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; // Check undef and ptr if !allow_ptr_and_undef { @@ -205,6 +210,9 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Ok(()) } + /// Writes `src` to the memory starting at `ptr.offset`. + /// + /// Will do bounds checks on the allocation. pub fn write_bytes( &mut self, cx: &impl HasDataLayout, @@ -216,6 +224,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Ok(()) } + /// Sets `count` bytes starting at `ptr.offset` with `val`. Basically `memset`. pub fn write_repeat( &mut self, cx: &impl HasDataLayout, @@ -236,6 +245,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// * byteorder cannot work with zero element buffers /// * in oder to obtain a `Pointer` we need to check for ZSTness anyway due to integer pointers /// being valid for ZSTs + /// + /// Note: This function does not do *any* alignment checks, you need to do these before calling pub fn read_scalar( &self, cx: &impl HasDataLayout, @@ -270,6 +281,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Ok(ScalarMaybeUndef::Scalar(Scalar::from_uint(bits, size))) } + /// Note: This function does not do *any* alignment checks, you need to do these before calling pub fn read_ptr_sized( &self, cx: &impl HasDataLayout, @@ -284,6 +296,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// * byteorder cannot work with zero element buffers /// * in oder to obtain a `Pointer` we need to check for ZSTness anyway due to integer pointers /// being valid for ZSTs + /// + /// Note: This function does not do *any* alignment checks, you need to do these before calling pub fn write_scalar( &mut self, cx: &impl HasDataLayout, @@ -330,6 +344,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Ok(()) } + /// Note: This function does not do *any* alignment checks, you need to do these before calling pub fn write_ptr_sized( &mut self, cx: &impl HasDataLayout, @@ -357,7 +372,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { self.relocations.range(Size::from_bytes(start)..end) } - /// Check that there ar eno relocations overlapping with the given range. + /// Check that there are no relocations overlapping with the given range. #[inline(always)] fn check_relocations( &self, From 22872196f55d93d7af6b3c96e34bef3579f0c3fc Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 17 Nov 2018 13:36:55 +0100 Subject: [PATCH 0225/1984] Factor out mplace offsetting into its own method --- src/librustc_mir/interpret/place.rs | 53 +++++++++++++++++------------ 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index d93aca7f4e1..0fd1a993cbd 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -159,6 +159,19 @@ impl MemPlace { Some(meta) => Immediate::ScalarPair(self.ptr.into(), meta.into()), } } + + pub fn offset( + self, + offset: Size, + meta: Option>, + cx: &impl HasDataLayout, + ) -> EvalResult<'tcx, Self> { + Ok(MemPlace { + ptr: self.ptr.ptr_offset(offset, cx)?, + align: self.align.restrict_for_offset(offset), + meta, + }) + } } impl<'tcx, Tag> MPlaceTy<'tcx, Tag> { @@ -174,6 +187,19 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> { } } + pub fn offset( + self, + offset: Size, + meta: Option>, + layout: TyLayout<'tcx>, + cx: &impl HasDataLayout, + ) -> EvalResult<'tcx, Self> { + Ok(MPlaceTy { + mplace: self.mplace.offset(offset, meta, cx)?, + layout, + }) + } + #[inline] fn from_aligned_ptr(ptr: Pointer, layout: TyLayout<'tcx>) -> Self { MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align.abi), layout } @@ -367,13 +393,9 @@ where (None, offset) }; - let ptr = base.ptr.ptr_offset(offset, self)?; - let align = base.align - // We do not look at `base.layout.align` nor `field_layout.align`, unlike - // codegen -- mostly to see if we can get away with that - .restrict_for_offset(offset); // must be last thing that happens - - Ok(MPlaceTy { mplace: MemPlace { ptr, align, meta }, layout: field_layout }) + // We do not look at `base.layout.align` nor `field_layout.align`, unlike + // codegen -- mostly to see if we can get away with that + base.offset(offset, meta, field_layout, self) } // Iterates over all fields of an array. Much more efficient than doing the @@ -391,14 +413,7 @@ where }; let layout = base.layout.field(self, 0)?; let dl = &self.tcx.data_layout; - Ok((0..len).map(move |i| { - let ptr = base.ptr.ptr_offset(i * stride, dl)?; - let align = base.align.restrict_for_offset(i * stride); - Ok(MPlaceTy { - mplace: MemPlace { ptr, align, meta: None }, - layout - }) - })) + Ok((0..len).map(move |i| base.offset(i * stride, None, layout, dl))) } pub fn mplace_subslice( @@ -417,8 +432,6 @@ where stride * from, _ => bug!("Unexpected layout of index access: {:#?}", base.layout), }; - let ptr = base.ptr.ptr_offset(from_offset, self)?; - let align = base.align.restrict_for_offset(from_offset); // Compute meta and new layout let inner_len = len - to - from; @@ -435,11 +448,7 @@ where bug!("cannot subslice non-array type: `{:?}`", base.layout.ty), }; let layout = self.layout_of(ty)?; - - Ok(MPlaceTy { - mplace: MemPlace { ptr, align, meta }, - layout - }) + base.offset(from_offset, meta, layout, self) } pub fn mplace_downcast( From 3220c0ce1afcb7b47671d6efe8fc38ab12d3d806 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 17 Nov 2018 16:18:05 +0100 Subject: [PATCH 0226/1984] Explain why vtable generation needs no alignment checks --- src/librustc_mir/interpret/traits.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index 37979c8ee66..bda585b8eda 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -59,6 +59,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let drop = ::monomorphize::resolve_drop_in_place(*tcx, ty); let drop = self.memory.create_fn_alloc(drop).with_default_tag(); + // no need to do any alignment checks on the memory accesses below, because we know the + // allocation is correctly aligned as we created it above. Also we're only offsetting by + // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`. self.memory .get_mut(vtable.alloc_id)? .write_ptr_sized(tcx, vtable, Scalar::Ptr(drop).into())?; From 360f9888bc143f6d7b2c09f723e255121bf49f8d Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 17 Nov 2018 17:52:25 +0100 Subject: [PATCH 0227/1984] update miri submodule --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index 06758c48bd7..dd7f545a69e 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 06758c48bd7a77bb5aa43fc50cf344540ba5afef +Subproject commit dd7f545a69e4b720407e458bf4ade0b207bbf9ee From b853252bcdb2ded2b049d833c51a993fe0ed40f8 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 20 Nov 2018 11:04:07 +0100 Subject: [PATCH 0228/1984] Rebase fallout --- src/librustc/mir/interpret/allocation.rs | 13 ++---------- src/librustc/mir/interpret/pointer.rs | 19 +++++++++++++++++- src/librustc_mir/interpret/memory.rs | 25 +++++++++++++++++++----- src/librustc_mir/interpret/operand.rs | 4 ++-- src/librustc_mir/interpret/validity.rs | 2 +- src/tools/miri | 2 +- 6 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 296c2e2dd6b..c612d6ad1bb 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -57,23 +57,14 @@ pub struct Allocation { impl<'tcx, Tag, Extra> Allocation { /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end /// of an allocation (i.e., at the first *inaccessible* location) *is* considered - /// in-bounds! This follows C's/LLVM's rules. `check` indicates whether we - /// additionally require the pointer to be pointing to a *live* (still allocated) - /// allocation. + /// in-bounds! This follows C's/LLVM's rules. /// If you want to check bounds before doing a memory access, better use `check_bounds`. pub fn check_bounds_ptr( &self, ptr: Pointer, ) -> EvalResult<'tcx> { let allocation_size = self.bytes.len() as u64; - if ptr.offset.bytes() > allocation_size { - return err!(PointerOutOfBounds { - ptr: ptr.erase_tag(), - check: InboundsCheck::Live, - allocation_size: Size::from_bytes(allocation_size), - }); - } - Ok(()) + ptr.check_in_alloc(Size::from_bytes(allocation_size), InboundsCheck::Live) } /// Check if the memory range beginning at `ptr` and of size `Size` is "in-bounds". diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index 969f2c0e837..a046825f088 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -2,7 +2,7 @@ use mir; use ty::layout::{self, HasDataLayout, Size}; use super::{ - AllocId, EvalResult, + AllocId, EvalResult, InboundsCheck, }; //////////////////////////////////////////////////////////////////////////////// @@ -148,4 +148,21 @@ impl<'tcx, Tag> Pointer { pub fn erase_tag(self) -> Pointer { Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () } } + + #[inline(always)] + pub fn check_in_alloc( + self, + allocation_size: Size, + check: InboundsCheck, + ) -> EvalResult<'tcx, ()> { + if self.offset > allocation_size { + err!(PointerOutOfBounds { + ptr: self.erase_tag(), + check, + allocation_size, + }) + } else { + Ok(()) + } + } } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 42500237645..c673b57a66f 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -28,9 +28,9 @@ use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use syntax::ast::Mutability; use super::{ - Pointer, AllocId, Allocation, GlobalId, AllocationExtra, InboundsCheck, + Pointer, AllocId, Allocation, GlobalId, AllocationExtra, EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic, - Machine, AllocMap, MayLeak, ErrorHandled, AllocationExtra, + Machine, AllocMap, MayLeak, ErrorHandled, InboundsCheck, }; #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] @@ -251,9 +251,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Scalar::Ptr(ptr) => { // check this is not NULL -- which we can ensure only if this is in-bounds // of some (potentially dead) allocation. - self.check_bounds_ptr(ptr, InboundsCheck::MaybeDead)?; - // data required for alignment check - let (_, align) = self.get_size_and_align(ptr.alloc_id); + let align = self.check_bounds_ptr_maybe_dead(ptr)?; (ptr.offset.bytes(), align) } Scalar::Bits { bits, size } => { @@ -284,6 +282,23 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { }) } } + + /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end + /// of an allocation (i.e., at the first *inaccessible* location) *is* considered + /// in-bounds! This follows C's/LLVM's rules. + /// This function also works for deallocated allocations. + /// Use `.get(ptr.alloc_id)?.check_bounds_ptr(ptr)` if you want to force the allocation + /// to still be live. + /// If you want to check bounds before doing a memory access, better first obtain + /// an `Allocation` and call `check_bounds`. + pub fn check_bounds_ptr_maybe_dead( + &self, + ptr: Pointer, + ) -> EvalResult<'tcx, Align> { + let (allocation_size, align) = self.get_size_and_align(ptr.alloc_id); + ptr.check_in_alloc(allocation_size, InboundsCheck::MaybeDead)?; + Ok(align) + } } /// Allocation accessors diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 9588a931c4a..539bc6d965f 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -19,7 +19,7 @@ use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerEx use rustc::mir::interpret::{ GlobalId, AllocId, ConstValue, Pointer, Scalar, - EvalResult, EvalErrorKind, InboundsCheck, + EvalResult, EvalErrorKind, }; use super::{EvalContext, Machine, MemPlace, MPlaceTy, MemoryKind}; pub use rustc::mir::interpret::ScalarMaybeUndef; @@ -647,7 +647,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) => { // The niche must be just 0 (which an inbounds pointer value never is) let ptr_valid = niche_start == 0 && variants_start == variants_end && - self.memory.check_bounds_ptr(ptr, InboundsCheck::MaybeDead).is_ok(); + self.memory.check_bounds_ptr_maybe_dead(ptr).is_ok(); if !ptr_valid { return err!(InvalidDiscriminant(raw_discr.erase_tag())); } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 8ce5a0365cf..ed4cb65ea74 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -17,7 +17,7 @@ use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx}; use rustc::ty; use rustc_data_structures::fx::FxHashSet; use rustc::mir::interpret::{ - Scalar, AllocType, EvalResult, EvalErrorKind, InboundsCheck, + Scalar, AllocType, EvalResult, EvalErrorKind, }; use super::{ diff --git a/src/tools/miri b/src/tools/miri index dd7f545a69e..32e93ed7762 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit dd7f545a69e4b720407e458bf4ade0b207bbf9ee +Subproject commit 32e93ed7762e5aa1a721636096848fc3c7bc7218 From 8d67de4e9165a643b74dae822be325a983beb10b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 24 Nov 2018 11:43:52 +0100 Subject: [PATCH 0229/1984] Don't show file sidebar by default --- src/librustdoc/html/static/source-script.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js index f8e0cf196fb..1db8218dae6 100644 --- a/src/librustdoc/html/static/source-script.js +++ b/src/librustdoc/html/static/source-script.js @@ -82,12 +82,12 @@ function toggleSidebar() { sidebar.style.left = ""; this.style.left = ""; child.innerText = "<"; - updateLocalStorage("rustdoc-source-sidebar-hidden", "false"); + updateLocalStorage("rustdoc-source-sidebar-show", "true"); } else { sidebar.style.left = "-300px"; this.style.left = "0"; child.innerText = ">"; - updateLocalStorage("rustdoc-source-sidebar-hidden", "true"); + updateLocalStorage("rustdoc-source-sidebar-show", "false"); } } @@ -101,11 +101,11 @@ function createSidebarToggle() { var inner2 = document.createElement("div"); inner2.style.marginTop = "-2px"; - if (getCurrentValue("rustdoc-source-sidebar-hidden") === "true") { + if (getCurrentValue("rustdoc-source-sidebar-show") === "true") { + inner2.innerText = "<"; + } else { inner2.innerText = ">"; sidebarToggle.style.left = "0"; - } else { - inner2.innerText = "<"; } inner1.appendChild(inner2); @@ -124,7 +124,7 @@ function createSourceSidebar() { var sidebar = document.createElement("div"); sidebar.id = "source-sidebar"; - if (getCurrentValue("rustdoc-source-sidebar-hidden") === "true") { + if (getCurrentValue("rustdoc-source-sidebar-show") !== "true") { sidebar.style.left = "-300px"; } From 1b432a612f24581717dc9d5f2f13873d187bb5bd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 24 Nov 2018 14:24:54 +0100 Subject: [PATCH 0230/1984] Add test for source files feature --- src/test/rustdoc/source-file.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/test/rustdoc/source-file.rs diff --git a/src/test/rustdoc/source-file.rs b/src/test/rustdoc/source-file.rs new file mode 100644 index 00000000000..077817bcf5b --- /dev/null +++ b/src/test/rustdoc/source-file.rs @@ -0,0 +1,15 @@ +// Copyright 2018 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. + +#![crate_name = "foo"] + +// @has source-files.js source-file.rs + +pub struct Foo; From 91f8e3721c65be79e45f75096fb46a969f5d26e6 Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 25 Nov 2018 00:25:29 +0800 Subject: [PATCH 0231/1984] Revert "appveyor: Use VS2017 for all our images" This reverts commit 008e5dcbd55cd751717ffd35a51dd65cd40011d4. --- appveyor.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index ac27211217a..f043b8bfefc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,8 +1,4 @@ environment: - # This is required for at least an AArch64 compiler in one image, and is - # otherwise recommended by AppVeyor currently for seeing if it has any - # affect on our job times. - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 Preview # By default schannel checks revocation of certificates unlike some other SSL # backends, but we've historically had problems on CI where a revocation @@ -91,6 +87,7 @@ environment: DIST_REQUIRE_ALL_TOOLS: 1 DEPLOY: 1 CI_JOB_NAME: dist-x86_64-msvc + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 Preview - RUST_CONFIGURE_ARGS: > --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc From b8a30f04cdd129ab89b85d0eda11f1c65058767a Mon Sep 17 00:00:00 2001 From: scalexm Date: Sat, 24 Nov 2018 23:34:44 +0100 Subject: [PATCH 0232/1984] Try to work around #53332 in `src/test/run-pass/rustc-rust-log.rs` --- src/test/run-pass/rustc-rust-log.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/run-pass/rustc-rust-log.rs b/src/test/run-pass/rustc-rust-log.rs index 8c3e4b391e9..10e91e71fe2 100644 --- a/src/test/run-pass/rustc-rust-log.rs +++ b/src/test/run-pass/rustc-rust-log.rs @@ -16,6 +16,7 @@ // // dont-check-compiler-stdout // dont-check-compiler-stderr +// compile-flags: --error-format human // rustc-env:RUST_LOG=debug From 6b338e034adfc1bffed942c084c892d34f1cd9b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 24 Nov 2018 16:23:11 -0800 Subject: [PATCH 0233/1984] Suggest correct enum variant on typo --- src/librustc_typeck/astconv.rs | 29 ++++++++++++++++++- src/test/ui/issues/issue-34209.rs | 4 +-- src/test/ui/issues/issue-34209.stderr | 7 ++--- src/test/ui/suggestions/suggest-variants.rs | 15 ++++++++++ .../ui/suggestions/suggest-variants.stderr | 20 +++++++++++++ 5 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/suggestions/suggest-variants.rs create mode 100644 src/test/ui/suggestions/suggest-variants.stderr diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a8164c85e82..4fbbe584452 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -36,8 +36,9 @@ use lint; use std::iter; use syntax::ast; -use syntax::ptr::P; use syntax::feature_gate::{GateIssue, emit_feature_err}; +use syntax::ptr::P; +use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::{DUMMY_SP, Span, MultiSpan}; pub trait AstConv<'gcx, 'tcx> { @@ -1303,6 +1304,32 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { Err(ErrorReported) => return (tcx.types.err, Def::Err), } } + (&ty::Adt(adt_def, _substs), Def::Enum(_did)) => { + let ty_str = ty.to_string(); + // Incorrect enum variant + let mut err = tcx.sess.struct_span_err( + span, + &format!("no variant `{}` on enum `{}`", &assoc_name.as_str(), ty_str), + ); + // Check if it was a typo + let input = adt_def.variants.iter().map(|variant| &variant.name); + if let Some(suggested_name) = find_best_match_for_name( + input, + &assoc_name.as_str(), + None, + ) { + err.span_suggestion_with_applicability( + span, + "did you mean", + format!("{}::{}", ty_str, suggested_name.to_string()), + Applicability::MaybeIncorrect, + ); + } else { + err.span_label(span, "unknown variant"); + } + err.emit(); + return (tcx.types.err, Def::Err); + } _ => { // Don't print TyErr to the user. if !ty.references_error() { diff --git a/src/test/ui/issues/issue-34209.rs b/src/test/ui/issues/issue-34209.rs index b3cb7d4cc30..86eb624edca 100644 --- a/src/test/ui/issues/issue-34209.rs +++ b/src/test/ui/issues/issue-34209.rs @@ -14,8 +14,8 @@ enum S { fn bug(l: S) { match l { - S::B{ } => { }, - //~^ ERROR ambiguous associated type + S::B { } => { }, + //~^ ERROR no variant `B` on enum `S` } } diff --git a/src/test/ui/issues/issue-34209.stderr b/src/test/ui/issues/issue-34209.stderr index 0dfdd8b5886..d5a5647422f 100644 --- a/src/test/ui/issues/issue-34209.stderr +++ b/src/test/ui/issues/issue-34209.stderr @@ -1,9 +1,8 @@ -error[E0223]: ambiguous associated type +error: no variant `B` on enum `S` --> $DIR/issue-34209.rs:17:9 | -LL | S::B{ } => { }, - | ^^^^ help: use fully-qualified syntax: `::B` +LL | S::B { } => { }, + | ^^^^ help: did you mean: `S::A` error: aborting due to previous error -For more information about this error, try `rustc --explain E0223`. diff --git a/src/test/ui/suggestions/suggest-variants.rs b/src/test/ui/suggestions/suggest-variants.rs new file mode 100644 index 00000000000..4a131ed837b --- /dev/null +++ b/src/test/ui/suggestions/suggest-variants.rs @@ -0,0 +1,15 @@ +#[derive(Debug)] +enum Shape { + Square { size: i32 }, + Circle { radius: i32 }, +} + +struct S { + x: usize, +} + +fn main() { + println!("My shape is {:?}", Shape::Squareee { size: 5}); + println!("My shape is {:?}", Shape::Circl { size: 5}); + println!("My shape is {:?}", Shape::Rombus{ size: 5}); +} diff --git a/src/test/ui/suggestions/suggest-variants.stderr b/src/test/ui/suggestions/suggest-variants.stderr new file mode 100644 index 00000000000..08ae68ea713 --- /dev/null +++ b/src/test/ui/suggestions/suggest-variants.stderr @@ -0,0 +1,20 @@ +error: no variant `Squareee` on enum `Shape` + --> $DIR/suggest-variants.rs:12:34 + | +LL | println!("My shape is {:?}", Shape::Squareee { size: 5}); + | ^^^^^^^^^^^^^^^ help: did you mean: `Shape::Square` + +error: no variant `Circl` on enum `Shape` + --> $DIR/suggest-variants.rs:13:34 + | +LL | println!("My shape is {:?}", Shape::Circl { size: 5}); + | ^^^^^^^^^^^^ help: did you mean: `Shape::Circle` + +error: no variant `Rombus` on enum `Shape` + --> $DIR/suggest-variants.rs:14:34 + | +LL | println!("My shape is {:?}", Shape::Rombus{ size: 5}); + | ^^^^^^^^^^^^^ unknown variant + +error: aborting due to 3 previous errors + From dce1c4530e2707c338fe56b26a36797377f11514 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 22 Nov 2018 13:05:25 -0500 Subject: [PATCH 0234/1984] [Windows] Work around non-monotonic clocks in the self-profiler On Windows, the high-resolution timestamp api doesn't seem to always be monotonic. This can cause panics when the self-profiler uses the `Instant` api to find elapsed time. Work around this by detecting the case where now is less than the start time and just use 0 elapsed ticks as the measurement. Fixes #51648 --- src/librustc/util/profiling.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/librustc/util/profiling.rs b/src/librustc/util/profiling.rs index 37073b6e820..1f050439764 100644 --- a/src/librustc/util/profiling.rs +++ b/src/librustc/util/profiling.rs @@ -12,7 +12,7 @@ use session::config::Options; use std::fs; use std::io::{self, StdoutLock, Write}; -use std::time::Instant; +use std::time::{Duration, Instant}; macro_rules! define_categories { ($($name:ident,)*) => { @@ -197,7 +197,20 @@ impl SelfProfiler { } fn stop_timer(&mut self) -> u64 { - let elapsed = self.current_timer.elapsed(); + let elapsed = if cfg!(windows) { + // On Windows, timers don't always appear to be monotonic (see #51648) + // which can lead to panics when calculating elapsed time. + // Work around this by testing to see if the current time is less than + // our recorded time, and if it is, just returning 0. + let now = Instant::now(); + if self.current_timer >= now { + Duration::new(0, 0) + } else { + self.current_timer.elapsed() + } + } else { + self.current_timer.elapsed() + }; self.current_timer = Instant::now(); From 1e34dfce6f49b5bef0da31a8abe34e753c3af513 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 2 Nov 2018 19:46:59 +1100 Subject: [PATCH 0235/1984] Update to `ena` 0.11.0. This version has some significant speed-ups relating to snapshotting. --- Cargo.lock | 6 +++--- src/librustc_data_structures/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc9296b81e2..a7b83f87b19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -661,7 +661,7 @@ dependencies = [ [[package]] name = "ena" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2230,7 +2230,7 @@ name = "rustc_data_structures" version = "0.0.0" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3295,7 +3295,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum elasticlunr-rs 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4837d77a1e157489a3933b743fd774ae75074e0e390b2b7f071530048a0d87ee" -"checksum ena 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25b4e5febb25f08c49f1b07dc33a182729a6b21edfb562b5aef95f78e0dbe5bb" +"checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" "checksum ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dc8393b3c7352f94092497f6b52019643e493b6b890eb417cdb7c46117e621" "checksum env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f4d7e69c283751083d53d01eac767407343b8b69c4bd70058e08adc2637cb257" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index 5b3dd38adf2..188919d0633 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -9,7 +9,7 @@ path = "lib.rs" crate-type = ["dylib"] [dependencies] -ena = "0.10.1" +ena = "0.11" log = "0.4" rustc_cratesio_shim = { path = "../librustc_cratesio_shim" } serialize = { path = "../libserialize" } From 9847b5cfcb16876630064ed766fbbb7545c67368 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 5 Nov 2018 09:28:12 +1100 Subject: [PATCH 0236/1984] Remove `insert_noop`. Because it's as useless as its name suggests. This commit also renames `UndoLog::Noop` as `UndoLog::Purged`, because (a) that's a more descriptive name and (b) it matches the name used in similar code in `librustc/infer/region_constraints/mod.rs`. --- src/librustc/traits/project.rs | 8 ++------ src/librustc_data_structures/snapshot_map/mod.rs | 14 ++++---------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index b59bd0e2388..e44bf2661c5 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1714,12 +1714,8 @@ impl<'tcx> ProjectionCache<'tcx> { /// to be a NormalizedTy. pub fn complete_normalized(&mut self, key: ProjectionCacheKey<'tcx>, ty: &NormalizedTy<'tcx>) { // We want to insert `ty` with no obligations. If the existing value - // already has no obligations (as is common) we can use `insert_noop` - // to do a minimal amount of work -- the HashMap insertion is skipped, - // and minimal changes are made to the undo log. - if ty.obligations.is_empty() { - self.map.insert_noop(); - } else { + // already has no obligations (as is common) we don't insert anything. + if !ty.obligations.is_empty() { self.map.insert(key, ProjectionCacheEntry::NormalizedTy(Normalized { value: ty.value, obligations: vec![] diff --git a/src/librustc_data_structures/snapshot_map/mod.rs b/src/librustc_data_structures/snapshot_map/mod.rs index 0b42cb1eddd..2c36a549bac 100644 --- a/src/librustc_data_structures/snapshot_map/mod.rs +++ b/src/librustc_data_structures/snapshot_map/mod.rs @@ -44,7 +44,7 @@ enum UndoLog { CommittedSnapshot, Inserted(K), Overwrite(K, V), - Noop, + Purged, } impl SnapshotMap @@ -72,12 +72,6 @@ impl SnapshotMap } } - pub fn insert_noop(&mut self) { - if !self.undo_log.is_empty() { - self.undo_log.push(UndoLog::Noop); - } - } - pub fn remove(&mut self, key: K) -> bool { match self.map.remove(&key) { Some(old_value) => { @@ -128,13 +122,13 @@ impl SnapshotMap let reverse = match self.undo_log[i] { UndoLog::OpenSnapshot => false, UndoLog::CommittedSnapshot => false, - UndoLog::Noop => false, + UndoLog::Purged => false, UndoLog::Inserted(ref k) => should_revert_key(k), UndoLog::Overwrite(ref k, _) => should_revert_key(k), }; if reverse { - let entry = mem::replace(&mut self.undo_log[i], UndoLog::Noop); + let entry = mem::replace(&mut self.undo_log[i], UndoLog::Purged); self.reverse(entry); } } @@ -171,7 +165,7 @@ impl SnapshotMap self.map.insert(key, old_value); } - UndoLog::Noop => {} + UndoLog::Purged => {} } } } From c86bbd4830410f19812ddbe4286ebb83ae043a4b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 5 Nov 2018 09:34:37 +1100 Subject: [PATCH 0237/1984] Rename `UndoLogEntry` as `UndoLog`. So that it matches `librustc_data_structures/snapshot_map/mod.rs` and the `ena` crate. --- src/librustc/infer/region_constraints/mod.rs | 10 +++++----- src/librustc/infer/region_constraints/taint.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 391bfc428c3..eb4c0d08f9f 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -11,7 +11,7 @@ //! See README.md use self::CombineMapType::*; -use self::UndoLogEntry::*; +use self::UndoLog::*; use super::unify_key; use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin}; @@ -59,7 +59,7 @@ pub struct RegionConstraintCollector<'tcx> { /// otherwise we end up adding entries for things like the lower /// bound on a variable and so forth, which can never be rolled /// back. - undo_log: Vec>, + undo_log: Vec>, /// When we add a R1 == R2 constriant, we currently add (a) edges /// R1 <= R2 and R2 <= R1 and (b) we unify the two regions in this @@ -254,7 +254,7 @@ struct TwoRegions<'tcx> { } #[derive(Copy, Clone, PartialEq)] -enum UndoLogEntry<'tcx> { +enum UndoLog<'tcx> { /// Pushed when we start a snapshot. OpenSnapshot, @@ -456,7 +456,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { self.any_unifications = snapshot.any_unifications; } - fn rollback_undo_entry(&mut self, undo_entry: UndoLogEntry<'tcx>) { + fn rollback_undo_entry(&mut self, undo_entry: UndoLog<'tcx>) { match undo_entry { OpenSnapshot => { panic!("Failure to observe stack discipline"); @@ -548,7 +548,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { fn kill_constraint<'tcx>( placeholders: &FxHashSet>, - undo_entry: &UndoLogEntry<'tcx>, + undo_entry: &UndoLog<'tcx>, ) -> bool { match undo_entry { &AddConstraint(Constraint::VarSubVar(..)) => false, diff --git a/src/librustc/infer/region_constraints/taint.rs b/src/librustc/infer/region_constraints/taint.rs index ef7365276f6..9f08fdcad7e 100644 --- a/src/librustc/infer/region_constraints/taint.rs +++ b/src/librustc/infer/region_constraints/taint.rs @@ -29,7 +29,7 @@ impl<'tcx> TaintSet<'tcx> { pub(super) fn fixed_point( &mut self, tcx: TyCtxt<'_, '_, 'tcx>, - undo_log: &[UndoLogEntry<'tcx>], + undo_log: &[UndoLog<'tcx>], verifys: &[Verify<'tcx>], ) { let mut prev_len = 0; From 7fe09a6551b72133e68911f3125f28642ec243ac Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 5 Nov 2018 09:35:28 +1100 Subject: [PATCH 0238/1984] Replace a `.truncate(0)` call with `.clear()`. --- src/librustc_data_structures/snapshot_map/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_data_structures/snapshot_map/mod.rs b/src/librustc_data_structures/snapshot_map/mod.rs index 2c36a549bac..6ad886625d8 100644 --- a/src/librustc_data_structures/snapshot_map/mod.rs +++ b/src/librustc_data_structures/snapshot_map/mod.rs @@ -106,7 +106,7 @@ impl SnapshotMap self.assert_open_snapshot(snapshot); if snapshot.len == 0 { // The root snapshot. - self.undo_log.truncate(0); + self.undo_log.clear(); } else { self.undo_log[snapshot.len] = UndoLog::CommittedSnapshot; } From f5624e41e819bb85408eba7b3abd550f61a2857a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 5 Nov 2018 10:37:23 +1100 Subject: [PATCH 0239/1984] Make `commit` and `rollback_to` methods take ownership of the snapshots. Because they shouldn't be reused. This provides consistency with the `ena` crate. --- src/librustc/infer/mod.rs | 2 +- src/librustc/traits/project.rs | 6 +++--- src/librustc_data_structures/snapshot_map/mod.rs | 8 ++++---- src/librustc_data_structures/snapshot_map/test.rs | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 87e32be1a17..9e51a4c16e5 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -790,7 +790,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.projection_cache .borrow_mut() - .commit(&projection_cache_snapshot); + .commit(projection_cache_snapshot); self.type_variables.borrow_mut().commit(type_snapshot); self.int_unification_table.borrow_mut().commit(int_snapshot); self.float_unification_table diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index e44bf2661c5..8f165863b3b 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1652,15 +1652,15 @@ impl<'tcx> ProjectionCache<'tcx> { } pub fn rollback_to(&mut self, snapshot: ProjectionCacheSnapshot) { - self.map.rollback_to(&snapshot.snapshot); + self.map.rollback_to(snapshot.snapshot); } pub fn rollback_placeholder(&mut self, snapshot: &ProjectionCacheSnapshot) { self.map.partial_rollback(&snapshot.snapshot, &|k| k.ty.has_re_skol()); } - pub fn commit(&mut self, snapshot: &ProjectionCacheSnapshot) { - self.map.commit(&snapshot.snapshot); + pub fn commit(&mut self, snapshot: ProjectionCacheSnapshot) { + self.map.commit(snapshot.snapshot); } /// Try to start normalize `key`; returns an error if diff --git a/src/librustc_data_structures/snapshot_map/mod.rs b/src/librustc_data_structures/snapshot_map/mod.rs index 6ad886625d8..8b761bdc8c6 100644 --- a/src/librustc_data_structures/snapshot_map/mod.rs +++ b/src/librustc_data_structures/snapshot_map/mod.rs @@ -102,8 +102,8 @@ impl SnapshotMap }); } - pub fn commit(&mut self, snapshot: &Snapshot) { - self.assert_open_snapshot(snapshot); + pub fn commit(&mut self, snapshot: Snapshot) { + self.assert_open_snapshot(&snapshot); if snapshot.len == 0 { // The root snapshot. self.undo_log.clear(); @@ -134,8 +134,8 @@ impl SnapshotMap } } - pub fn rollback_to(&mut self, snapshot: &Snapshot) { - self.assert_open_snapshot(snapshot); + pub fn rollback_to(&mut self, snapshot: Snapshot) { + self.assert_open_snapshot(&snapshot); while self.undo_log.len() > snapshot.len + 1 { let entry = self.undo_log.pop().unwrap(); self.reverse(entry); diff --git a/src/librustc_data_structures/snapshot_map/test.rs b/src/librustc_data_structures/snapshot_map/test.rs index 700f9c95e3b..67be806261b 100644 --- a/src/librustc_data_structures/snapshot_map/test.rs +++ b/src/librustc_data_structures/snapshot_map/test.rs @@ -20,7 +20,7 @@ fn basic() { map.insert(44, "fourty-four"); assert_eq!(map[&44], "fourty-four"); assert_eq!(map.get(&33), None); - map.rollback_to(&snapshot); + map.rollback_to(snapshot); assert_eq!(map[&22], "twenty-two"); assert_eq!(map.get(&33), None); assert_eq!(map.get(&44), None); @@ -33,7 +33,7 @@ fn out_of_order() { map.insert(22, "twenty-two"); let snapshot1 = map.snapshot(); let _snapshot2 = map.snapshot(); - map.rollback_to(&snapshot1); + map.rollback_to(snapshot1); } #[test] @@ -43,8 +43,8 @@ fn nested_commit_then_rollback() { let snapshot1 = map.snapshot(); let snapshot2 = map.snapshot(); map.insert(22, "thirty-three"); - map.commit(&snapshot2); + map.commit(snapshot2); assert_eq!(map[&22], "thirty-three"); - map.rollback_to(&snapshot1); + map.rollback_to(snapshot1); assert_eq!(map[&22], "twenty-two"); } From f23c969492fe5aeb2e33316032387175020d2672 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 5 Nov 2018 10:44:52 +1100 Subject: [PATCH 0240/1984] Introduce `in_snapshot` and `assert_open_snapshot` methods. This makes the two snapshot implementations more consistent with each other and with crate `ena`. --- src/librustc/infer/region_constraints/mod.rs | 11 +++++++---- src/librustc_data_structures/snapshot_map/mod.rs | 10 +++++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index eb4c0d08f9f..231eff9ff9f 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -429,10 +429,14 @@ impl<'tcx> RegionConstraintCollector<'tcx> { } } - pub fn commit(&mut self, snapshot: RegionSnapshot) { - debug!("RegionConstraintCollector: commit({})", snapshot.length); + fn assert_open_snapshot(&self, snapshot: &RegionSnapshot) { assert!(self.undo_log.len() > snapshot.length); assert!(self.undo_log[snapshot.length] == OpenSnapshot); + } + + pub fn commit(&mut self, snapshot: RegionSnapshot) { + debug!("RegionConstraintCollector: commit({})", snapshot.length); + self.assert_open_snapshot(&snapshot); if snapshot.length == 0 { self.undo_log.clear(); @@ -444,8 +448,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { pub fn rollback_to(&mut self, snapshot: RegionSnapshot) { debug!("RegionConstraintCollector: rollback_to({:?})", snapshot); - assert!(self.undo_log.len() > snapshot.length); - assert!(self.undo_log[snapshot.length] == OpenSnapshot); + self.assert_open_snapshot(&snapshot); while self.undo_log.len() > snapshot.length + 1 { let undo_entry = self.undo_log.pop().unwrap(); self.rollback_undo_entry(undo_entry); diff --git a/src/librustc_data_structures/snapshot_map/mod.rs b/src/librustc_data_structures/snapshot_map/mod.rs index 8b761bdc8c6..a480499a30c 100644 --- a/src/librustc_data_structures/snapshot_map/mod.rs +++ b/src/librustc_data_structures/snapshot_map/mod.rs @@ -55,16 +55,20 @@ impl SnapshotMap self.undo_log.clear(); } + fn in_snapshot(&self) -> bool { + !self.undo_log.is_empty() + } + pub fn insert(&mut self, key: K, value: V) -> bool { match self.map.insert(key.clone(), value) { None => { - if !self.undo_log.is_empty() { + if self.in_snapshot() { self.undo_log.push(UndoLog::Inserted(key)); } true } Some(old_value) => { - if !self.undo_log.is_empty() { + if self.in_snapshot() { self.undo_log.push(UndoLog::Overwrite(key, old_value)); } false @@ -75,7 +79,7 @@ impl SnapshotMap pub fn remove(&mut self, key: K) -> bool { match self.map.remove(&key) { Some(old_value) => { - if !self.undo_log.is_empty() { + if self.in_snapshot() { self.undo_log.push(UndoLog::Overwrite(key, old_value)); } true From 2d68fa07bff2b417094024597790d30acd501ab3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 5 Nov 2018 10:59:33 +1100 Subject: [PATCH 0241/1984] Remove `OpenSnapshot` and `CommittedSnapshot` markers from `SnapshotMap`. They're not strictly necessary, and they result in the `Vec` being allocated even for the trivial (and common) case where a `start_snapshot` is immediately followed by a `commit` or `rollback_to`. --- .../snapshot_map/mod.rs | 48 +++++++------------ .../snapshot_map/test.rs | 11 +++-- 2 files changed, 25 insertions(+), 34 deletions(-) diff --git a/src/librustc_data_structures/snapshot_map/mod.rs b/src/librustc_data_structures/snapshot_map/mod.rs index a480499a30c..c256506a19d 100644 --- a/src/librustc_data_structures/snapshot_map/mod.rs +++ b/src/librustc_data_structures/snapshot_map/mod.rs @@ -21,6 +21,7 @@ pub struct SnapshotMap { map: FxHashMap, undo_log: Vec>, + num_open_snapshots: usize, } // HACK(eddyb) manual impl avoids `Default` bounds on `K` and `V`. @@ -31,6 +32,7 @@ impl Default for SnapshotMap SnapshotMap { map: Default::default(), undo_log: Default::default(), + num_open_snapshots: 0, } } } @@ -40,8 +42,6 @@ pub struct Snapshot { } enum UndoLog { - OpenSnapshot, - CommittedSnapshot, Inserted(K), Overwrite(K, V), Purged, @@ -53,10 +53,11 @@ impl SnapshotMap pub fn clear(&mut self) { self.map.clear(); self.undo_log.clear(); + self.num_open_snapshots = 0; } fn in_snapshot(&self) -> bool { - !self.undo_log.is_empty() + self.num_open_snapshots > 0 } pub fn insert(&mut self, key: K, value: V) -> bool { @@ -93,27 +94,27 @@ impl SnapshotMap } pub fn snapshot(&mut self) -> Snapshot { - self.undo_log.push(UndoLog::OpenSnapshot); - let len = self.undo_log.len() - 1; + let len = self.undo_log.len(); + self.num_open_snapshots += 1; Snapshot { len } } fn assert_open_snapshot(&self, snapshot: &Snapshot) { - assert!(snapshot.len < self.undo_log.len()); - assert!(match self.undo_log[snapshot.len] { - UndoLog::OpenSnapshot => true, - _ => false, - }); + assert!(self.undo_log.len() >= snapshot.len); + assert!(self.num_open_snapshots > 0); } pub fn commit(&mut self, snapshot: Snapshot) { self.assert_open_snapshot(&snapshot); - if snapshot.len == 0 { - // The root snapshot. + if self.num_open_snapshots == 1 { + // The root snapshot. It's safe to clear the undo log because + // there's no snapshot further out that we might need to roll back + // to. + assert!(snapshot.len == 0); self.undo_log.clear(); - } else { - self.undo_log[snapshot.len] = UndoLog::CommittedSnapshot; } + + self.num_open_snapshots -= 1; } pub fn partial_rollback(&mut self, @@ -122,10 +123,8 @@ impl SnapshotMap where F: Fn(&K) -> bool { self.assert_open_snapshot(snapshot); - for i in (snapshot.len + 1..self.undo_log.len()).rev() { + for i in (snapshot.len .. self.undo_log.len()).rev() { let reverse = match self.undo_log[i] { - UndoLog::OpenSnapshot => false, - UndoLog::CommittedSnapshot => false, UndoLog::Purged => false, UndoLog::Inserted(ref k) => should_revert_key(k), UndoLog::Overwrite(ref k, _) => should_revert_key(k), @@ -140,27 +139,16 @@ impl SnapshotMap pub fn rollback_to(&mut self, snapshot: Snapshot) { self.assert_open_snapshot(&snapshot); - while self.undo_log.len() > snapshot.len + 1 { + while self.undo_log.len() > snapshot.len { let entry = self.undo_log.pop().unwrap(); self.reverse(entry); } - let v = self.undo_log.pop().unwrap(); - assert!(match v { - UndoLog::OpenSnapshot => true, - _ => false, - }); - assert!(self.undo_log.len() == snapshot.len); + self.num_open_snapshots -= 1; } fn reverse(&mut self, entry: UndoLog) { match entry { - UndoLog::OpenSnapshot => { - panic!("cannot rollback an uncommitted snapshot"); - } - - UndoLog::CommittedSnapshot => {} - UndoLog::Inserted(key) => { self.map.remove(&key); } diff --git a/src/librustc_data_structures/snapshot_map/test.rs b/src/librustc_data_structures/snapshot_map/test.rs index 67be806261b..b4ecb85fc43 100644 --- a/src/librustc_data_structures/snapshot_map/test.rs +++ b/src/librustc_data_structures/snapshot_map/test.rs @@ -17,8 +17,8 @@ fn basic() { let snapshot = map.snapshot(); map.insert(22, "thirty-three"); assert_eq!(map[&22], "thirty-three"); - map.insert(44, "fourty-four"); - assert_eq!(map[&44], "fourty-four"); + map.insert(44, "forty-four"); + assert_eq!(map[&44], "forty-four"); assert_eq!(map.get(&33), None); map.rollback_to(snapshot); assert_eq!(map[&22], "twenty-two"); @@ -32,8 +32,11 @@ fn out_of_order() { let mut map = SnapshotMap::default(); map.insert(22, "twenty-two"); let snapshot1 = map.snapshot(); - let _snapshot2 = map.snapshot(); - map.rollback_to(snapshot1); + map.insert(33, "thirty-three"); + let snapshot2 = map.snapshot(); + map.insert(44, "forty-four"); + map.rollback_to(snapshot1); // bogus, but accepted + map.rollback_to(snapshot2); // asserts } #[test] From 94967ae8c1129d63df4446240df4fc45a57c8164 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 5 Nov 2018 12:21:54 +1100 Subject: [PATCH 0242/1984] Remove `OpenSnapshot` and `CommittedSnapshot` markers from `RegionConstraintCollector`. They're not strictly necessary, and they result in the `Vec` being allocated even for the trivial (and common) case where a `start_snapshot` is immediately followed by a `commit` or `rollback_to`. The commit also removes a now-unnecessary argument of `pop_placeholders()`. --- src/librustc/infer/higher_ranked/mod.rs | 6 +- src/librustc/infer/region_constraints/mod.rs | 65 +++++++++---------- .../infer/region_constraints/taint.rs | 3 +- 3 files changed, 32 insertions(+), 42 deletions(-) diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index 8172f620c36..4e203b986df 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -543,11 +543,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ) { debug!("pop_placeholders({:?})", placeholder_map); let placeholder_regions: FxHashSet<_> = placeholder_map.values().cloned().collect(); - self.borrow_region_constraints() - .pop_placeholders( - &placeholder_regions, - &snapshot.region_constraints_snapshot, - ); + self.borrow_region_constraints().pop_placeholders(&placeholder_regions); self.universe.set(snapshot.universe); if !placeholder_map.is_empty() { self.projection_cache.borrow_mut().rollback_placeholder( diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 231eff9ff9f..af1b6964b81 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -52,15 +52,18 @@ pub struct RegionConstraintCollector<'tcx> { /// The undo log records actions that might later be undone. /// - /// Note: when the undo_log is empty, we are not actively + /// Note: `num_open_snapshots` is used to track if we are actively /// snapshotting. When the `start_snapshot()` method is called, we - /// push an OpenSnapshot entry onto the list to indicate that we - /// are now actively snapshotting. The reason for this is that - /// otherwise we end up adding entries for things like the lower - /// bound on a variable and so forth, which can never be rolled - /// back. + /// increment `num_open_snapshots` to indicate that we are now actively + /// snapshotting. The reason for this is that otherwise we end up adding + /// entries for things like the lower bound on a variable and so forth, + /// which can never be rolled back. undo_log: Vec>, + /// The number of open snapshots, i.e. those that haven't been committed or + /// rolled back. + num_open_snapshots: usize, + /// When we add a R1 == R2 constriant, we currently add (a) edges /// R1 <= R2 and R2 <= R1 and (b) we unify the two regions in this /// table. You can then call `opportunistic_resolve_var` early @@ -255,14 +258,6 @@ struct TwoRegions<'tcx> { #[derive(Copy, Clone, PartialEq)] enum UndoLog<'tcx> { - /// Pushed when we start a snapshot. - OpenSnapshot, - - /// Replaces an `OpenSnapshot` when a snapshot is committed, but - /// that snapshot is not the root. If the root snapshot is - /// unrolled, all nested snapshots must be committed. - CommitedSnapshot, - /// We added `RegionVid` AddVar(RegionVid), @@ -387,6 +382,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { glbs, bound_count: _, undo_log: _, + num_open_snapshots: _, unification_table, any_unifications, } = self; @@ -415,13 +411,13 @@ impl<'tcx> RegionConstraintCollector<'tcx> { } fn in_snapshot(&self) -> bool { - !self.undo_log.is_empty() + self.num_open_snapshots > 0 } pub fn start_snapshot(&mut self) -> RegionSnapshot { let length = self.undo_log.len(); debug!("RegionConstraintCollector: start_snapshot({})", length); - self.undo_log.push(OpenSnapshot); + self.num_open_snapshots += 1; RegionSnapshot { length, region_snapshot: self.unification_table.snapshot(), @@ -430,41 +426,45 @@ impl<'tcx> RegionConstraintCollector<'tcx> { } fn assert_open_snapshot(&self, snapshot: &RegionSnapshot) { - assert!(self.undo_log.len() > snapshot.length); - assert!(self.undo_log[snapshot.length] == OpenSnapshot); + assert!(self.undo_log.len() >= snapshot.length); + assert!(self.num_open_snapshots > 0); } pub fn commit(&mut self, snapshot: RegionSnapshot) { debug!("RegionConstraintCollector: commit({})", snapshot.length); self.assert_open_snapshot(&snapshot); - if snapshot.length == 0 { + if self.num_open_snapshots == 1 { + // The root snapshot. It's safe to clear the undo log because + // there's no snapshot further out that we might need to roll back + // to. + assert!(snapshot.length == 0); self.undo_log.clear(); - } else { - (*self.undo_log)[snapshot.length] = CommitedSnapshot; } + + self.num_open_snapshots -= 1; + self.unification_table.commit(snapshot.region_snapshot); } pub fn rollback_to(&mut self, snapshot: RegionSnapshot) { debug!("RegionConstraintCollector: rollback_to({:?})", snapshot); self.assert_open_snapshot(&snapshot); - while self.undo_log.len() > snapshot.length + 1 { + + while self.undo_log.len() > snapshot.length { let undo_entry = self.undo_log.pop().unwrap(); self.rollback_undo_entry(undo_entry); } - let c = self.undo_log.pop().unwrap(); - assert!(c == OpenSnapshot); + + self.num_open_snapshots -= 1; + self.unification_table.rollback_to(snapshot.region_snapshot); self.any_unifications = snapshot.any_unifications; } fn rollback_undo_entry(&mut self, undo_entry: UndoLog<'tcx>) { match undo_entry { - OpenSnapshot => { - panic!("Failure to observe stack discipline"); - } - Purged | CommitedSnapshot => { + Purged => { // nothing to do here } AddVar(vid) => { @@ -524,15 +524,10 @@ impl<'tcx> RegionConstraintCollector<'tcx> { /// in `skols`. This is used after a higher-ranked operation /// completes to remove all trace of the placeholder regions /// created in that time. - pub fn pop_placeholders( - &mut self, - placeholders: &FxHashSet>, - snapshot: &RegionSnapshot, - ) { + pub fn pop_placeholders(&mut self, placeholders: &FxHashSet>) { debug!("pop_placeholders(placeholders={:?})", placeholders); assert!(self.in_snapshot()); - assert!(self.undo_log[snapshot.length] == OpenSnapshot); let constraints_to_kill: Vec = self.undo_log .iter() @@ -565,7 +560,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { &AddCombination(_, ref two_regions) => { placeholders.contains(&two_regions.a) || placeholders.contains(&two_regions.b) } - &AddVar(..) | &OpenSnapshot | &Purged | &CommitedSnapshot => false, + &AddVar(..) | &Purged => false, } } } diff --git a/src/librustc/infer/region_constraints/taint.rs b/src/librustc/infer/region_constraints/taint.rs index 9f08fdcad7e..27ce7f10603 100644 --- a/src/librustc/infer/region_constraints/taint.rs +++ b/src/librustc/infer/region_constraints/taint.rs @@ -65,8 +65,7 @@ impl<'tcx> TaintSet<'tcx> { "we never add verifications while doing higher-ranked things", ) } - &Purged | &AddCombination(..) | &AddVar(..) | &OpenSnapshot - | &CommitedSnapshot => {} + &Purged | &AddCombination(..) | &AddVar(..) => {} } } } From 68a26ec647147d70bcd7f0e7f56a0bf9fedb5f06 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sun, 25 Nov 2018 08:26:22 +0100 Subject: [PATCH 0243/1984] Stabilize the int_to_from_bytes feature Fixes #52963 --- src/libcore/num/mod.rs | 48 ++++++---------------- src/test/run-pass/const-int-conversion.rs | 2 +- src/test/ui/consts/const-int-conversion.rs | 2 +- 3 files changed, 14 insertions(+), 38 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 30b7b454684..9deae124829 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1921,12 +1921,10 @@ big-endian (network) byte order. # Examples ``` -#![feature(int_to_from_bytes)] - let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes(); assert_eq!(bytes, ", $be_bytes, "); ```"), - #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { @@ -1941,12 +1939,10 @@ little-endian byte order. # Examples ``` -#![feature(int_to_from_bytes)] - let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes(); assert_eq!(bytes, ", $le_bytes, "); ```"), - #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { @@ -1969,8 +1965,6 @@ instead. # Examples ``` -#![feature(int_to_from_bytes)] - let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes(); assert_eq!(bytes, if cfg!(target_endian = \"big\") { ", $be_bytes, " @@ -1978,7 +1972,7 @@ assert_eq!(bytes, if cfg!(target_endian = \"big\") { ", $le_bytes, " }); ```"), - #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { @@ -1993,12 +1987,10 @@ big endian. # Examples ``` -#![feature(int_to_from_bytes)] - let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, "); assert_eq!(value, ", $swap_op, "); ```"), - #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { @@ -2014,12 +2006,10 @@ little endian. # Examples ``` -#![feature(int_to_from_bytes)] - let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, "); assert_eq!(value, ", $swap_op, "); ```"), - #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { @@ -2041,8 +2031,6 @@ appropriate instead. # Examples ``` -#![feature(int_to_from_bytes)] - let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") { ", $be_bytes, " } else { @@ -2050,7 +2038,7 @@ let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"bi }); assert_eq!(value, ", $swap_op, "); ```"), - #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { @@ -3663,12 +3651,10 @@ big-endian (network) byte order. # Examples ``` -#![feature(int_to_from_bytes)] - let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes(); assert_eq!(bytes, ", $be_bytes, "); ```"), - #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { @@ -3683,12 +3669,10 @@ little-endian byte order. # Examples ``` -#![feature(int_to_from_bytes)] - let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes(); assert_eq!(bytes, ", $le_bytes, "); ```"), - #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { @@ -3711,8 +3695,6 @@ instead. # Examples ``` -#![feature(int_to_from_bytes)] - let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes(); assert_eq!(bytes, if cfg!(target_endian = \"big\") { ", $be_bytes, " @@ -3720,7 +3702,7 @@ assert_eq!(bytes, if cfg!(target_endian = \"big\") { ", $le_bytes, " }); ```"), - #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { @@ -3735,12 +3717,10 @@ big endian. # Examples ``` -#![feature(int_to_from_bytes)] - let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, "); assert_eq!(value, ", $swap_op, "); ```"), - #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { @@ -3756,12 +3736,10 @@ little endian. # Examples ``` -#![feature(int_to_from_bytes)] - let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, "); assert_eq!(value, ", $swap_op, "); ```"), - #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { @@ -3783,8 +3761,6 @@ appropriate instead. # Examples ``` -#![feature(int_to_from_bytes)] - let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") { ", $be_bytes, " } else { @@ -3792,7 +3768,7 @@ let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"bi }); assert_eq!(value, ", $swap_op, "); ```"), - #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] #[inline] pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { diff --git a/src/test/run-pass/const-int-conversion.rs b/src/test/run-pass/const-int-conversion.rs index 790c62288d3..e199c438585 100644 --- a/src/test/run-pass/const-int-conversion.rs +++ b/src/test/run-pass/const-int-conversion.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(const_int_conversion, const_int_ops, reverse_bits, int_to_from_bytes)] +#![feature(const_int_conversion, const_int_ops, reverse_bits)] const REVERSE: u32 = 0x12345678_u32.reverse_bits(); const FROM_BE_BYTES: i32 = i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]); diff --git a/src/test/ui/consts/const-int-conversion.rs b/src/test/ui/consts/const-int-conversion.rs index 0abe6b4a1e4..2a20f0df15c 100644 --- a/src/test/ui/consts/const-int-conversion.rs +++ b/src/test/ui/consts/const-int-conversion.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(reverse_bits, int_to_from_bytes)] +#![feature(reverse_bits)] fn main() { let x: &'static i32 = &(5_i32.reverse_bits()); From 4c090fe310e32300bd6c6a0610f3f23366ea1445 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 14 Nov 2018 16:00:52 +0100 Subject: [PATCH 0244/1984] bring back MemoryExtra --- src/librustc/mir/interpret/allocation.rs | 250 ++++++++++++++--------- src/librustc/ty/context.rs | 2 +- src/librustc_mir/const_eval.rs | 1 + src/librustc_mir/interpret/machine.rs | 7 +- src/librustc_mir/interpret/memory.rs | 22 +- src/librustc_mir/interpret/place.rs | 4 +- 6 files changed, 179 insertions(+), 107 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index c612d6ad1bb..b1e92ef4b51 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -53,6 +53,94 @@ pub struct Allocation { pub extra: Extra, } + +pub trait AllocationExtra: ::std::fmt::Debug + Clone { + /// Hook to initialize the extra data when an allocation gets crated. + fn memory_allocated( + _size: Size, + _memory_extra: &MemoryExtra + ) -> EvalResult<'tcx, Self>; + + /// Hook for performing extra checks on a memory read access. + /// + /// Takes read-only access to the allocation so we can keep all the memory read + /// operations take `&self`. Use a `RefCell` in `AllocExtra` if you + /// need to mutate. + #[inline(always)] + fn memory_read( + _alloc: &Allocation, + _ptr: Pointer, + _size: Size, + ) -> EvalResult<'tcx> { + Ok(()) + } + + /// Hook for performing extra checks on a memory write access. + #[inline(always)] + fn memory_written( + _alloc: &mut Allocation, + _ptr: Pointer, + _size: Size, + ) -> EvalResult<'tcx> { + Ok(()) + } + + /// Hook for performing extra checks on a memory deallocation. + /// `size` will be the size of the allocation. + #[inline(always)] + fn memory_deallocated( + _alloc: &mut Allocation, + _ptr: Pointer, + _size: Size, + ) -> EvalResult<'tcx> { + Ok(()) + } +} + +impl AllocationExtra<(), ()> for () { + #[inline(always)] + fn memory_allocated( + _size: Size, + _memory_extra: &() + ) -> EvalResult<'tcx, Self> { + Ok(()) + } +} + +impl Allocation { + /// Creates a read-only allocation initialized by the given bytes + pub fn from_bytes(slice: &[u8], align: Align, extra: Extra) -> Self { + let mut undef_mask = UndefMask::new(Size::ZERO); + undef_mask.grow(Size::from_bytes(slice.len() as u64), true); + Self { + bytes: slice.to_owned(), + relocations: Relocations::new(), + undef_mask, + align, + mutability: Mutability::Immutable, + extra, + } + } + + pub fn from_byte_aligned_bytes(slice: &[u8], extra: Extra) -> Self { + Allocation::from_bytes(slice, Align::from_bytes(1).unwrap(), extra) + } + + pub fn undef(size: Size, align: Align, extra: Extra) -> Self { + assert_eq!(size.bytes() as usize as u64, size.bytes()); + Allocation { + bytes: vec![0; size.bytes() as usize], + relocations: Relocations::new(), + undef_mask: UndefMask::new(size), + align, + mutability: Mutability::Mutable, + extra, + } + } +} + +impl<'tcx> ::serialize::UseSpecializedDecodable for &'tcx Allocation {} + /// Alignment and bounds checks impl<'tcx, Tag, Extra> Allocation { /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end @@ -81,7 +169,7 @@ impl<'tcx, Tag, Extra> Allocation { } /// Byte accessors -impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { +impl<'tcx, Tag: Copy, Extra> Allocation { /// The last argument controls whether we error out when there are undefined /// or pointer bytes. You should never call this, call `get_bytes` or /// `get_bytes_with_undef_and_ptr` instead, @@ -89,13 +177,16 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// This function also guarantees that the resulting pointer will remain stable /// even when new allocations are pushed to the `HashMap`. `copy_repeatedly` relies /// on that. - fn get_bytes_internal( + fn get_bytes_internal( &self, cx: &impl HasDataLayout, ptr: Pointer, size: Size, check_defined_and_ptr: bool, - ) -> EvalResult<'tcx, &[u8]> { + ) -> EvalResult<'tcx, &[u8]> + // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 + where Extra: AllocationExtra + { self.check_bounds(cx, ptr, size)?; if check_defined_and_ptr { @@ -115,35 +206,44 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { } #[inline] - pub fn get_bytes( + pub fn get_bytes( &self, cx: &impl HasDataLayout, ptr: Pointer, size: Size, - ) -> EvalResult<'tcx, &[u8]> { + ) -> EvalResult<'tcx, &[u8]> + // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 + where Extra: AllocationExtra + { self.get_bytes_internal(cx, ptr, size, true) } /// It is the caller's responsibility to handle undefined and pointer bytes. /// However, this still checks that there are no relocations on the *edges*. #[inline] - pub fn get_bytes_with_undef_and_ptr( + pub fn get_bytes_with_undef_and_ptr( &self, cx: &impl HasDataLayout, ptr: Pointer, size: Size, - ) -> EvalResult<'tcx, &[u8]> { + ) -> EvalResult<'tcx, &[u8]> + // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 + where Extra: AllocationExtra + { self.get_bytes_internal(cx, ptr, size, false) } /// Just calling this already marks everything as defined and removes relocations, /// so be sure to actually put data there! - pub fn get_bytes_mut( + pub fn get_bytes_mut( &mut self, cx: &impl HasDataLayout, ptr: Pointer, size: Size, - ) -> EvalResult<'tcx, &mut [u8]> { + ) -> EvalResult<'tcx, &mut [u8]> + // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 + where Extra: AllocationExtra + { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); self.check_bounds(cx, ptr, size)?; @@ -160,14 +260,17 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { } /// Reading and writing -impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { +impl<'tcx, Tag: Copy, Extra> Allocation { /// Reads bytes until a `0` is encountered. Will error if the end of the allocation is reached /// before a `0` is found. - pub fn read_c_str( + pub fn read_c_str( &self, cx: &impl HasDataLayout, ptr: Pointer, - ) -> EvalResult<'tcx, &[u8]> { + ) -> EvalResult<'tcx, &[u8]> + // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 + where Extra: AllocationExtra + { assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); let offset = ptr.offset.bytes() as usize; match self.bytes[offset..].iter().position(|&c| c == 0) { @@ -184,13 +287,16 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Validates that `ptr.offset` and `ptr.offset + size` do not point to the middle of a /// relocation. If `allow_ptr_and_undef` is `false`, also enforces that the memory in the /// given range contains neither relocations nor undef bytes. - pub fn check_bytes( + pub fn check_bytes( &self, cx: &impl HasDataLayout, ptr: Pointer, size: Size, allow_ptr_and_undef: bool, - ) -> EvalResult<'tcx> { + ) -> EvalResult<'tcx> + // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 + where Extra: AllocationExtra + { // Check bounds and relocations on the edges self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; // Check undef and ptr @@ -204,25 +310,31 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Writes `src` to the memory starting at `ptr.offset`. /// /// Will do bounds checks on the allocation. - pub fn write_bytes( + pub fn write_bytes( &mut self, cx: &impl HasDataLayout, ptr: Pointer, src: &[u8], - ) -> EvalResult<'tcx> { + ) -> EvalResult<'tcx> + // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 + where Extra: AllocationExtra + { let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64))?; bytes.clone_from_slice(src); Ok(()) } /// Sets `count` bytes starting at `ptr.offset` with `val`. Basically `memset`. - pub fn write_repeat( + pub fn write_repeat( &mut self, cx: &impl HasDataLayout, ptr: Pointer, val: u8, count: Size - ) -> EvalResult<'tcx> { + ) -> EvalResult<'tcx> + // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 + where Extra: AllocationExtra + { let bytes = self.get_bytes_mut(cx, ptr, count)?; for b in bytes { *b = val; @@ -238,12 +350,15 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// being valid for ZSTs /// /// Note: This function does not do *any* alignment checks, you need to do these before calling - pub fn read_scalar( + pub fn read_scalar( &self, cx: &impl HasDataLayout, ptr: Pointer, size: Size - ) -> EvalResult<'tcx, ScalarMaybeUndef> { + ) -> EvalResult<'tcx, ScalarMaybeUndef> + // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 + where Extra: AllocationExtra + { // get_bytes_unchecked tests relocation edges let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; // Undef check happens *after* we established that the alignment is correct. @@ -273,11 +388,14 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { } /// Note: This function does not do *any* alignment checks, you need to do these before calling - pub fn read_ptr_sized( + pub fn read_ptr_sized( &self, cx: &impl HasDataLayout, ptr: Pointer, - ) -> EvalResult<'tcx, ScalarMaybeUndef> { + ) -> EvalResult<'tcx, ScalarMaybeUndef> + // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 + where Extra: AllocationExtra + { self.read_scalar(cx, ptr, cx.data_layout().pointer_size) } @@ -289,13 +407,16 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// being valid for ZSTs /// /// Note: This function does not do *any* alignment checks, you need to do these before calling - pub fn write_scalar( + pub fn write_scalar( &mut self, cx: &impl HasDataLayout, ptr: Pointer, val: ScalarMaybeUndef, type_size: Size, - ) -> EvalResult<'tcx> { + ) -> EvalResult<'tcx> + // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 + where Extra: AllocationExtra + { let val = match val { ScalarMaybeUndef::Scalar(scalar) => scalar, ScalarMaybeUndef::Undef => return self.mark_definedness(ptr, type_size, false), @@ -336,12 +457,15 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { } /// Note: This function does not do *any* alignment checks, you need to do these before calling - pub fn write_ptr_sized( + pub fn write_ptr_sized( &mut self, cx: &impl HasDataLayout, ptr: Pointer, val: ScalarMaybeUndef - ) -> EvalResult<'tcx> { + ) -> EvalResult<'tcx> + // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 + where Extra: AllocationExtra + { let ptr_size = cx.data_layout().pointer_size; self.write_scalar(cx, ptr.into(), val, ptr_size) } @@ -465,79 +589,7 @@ impl<'tcx, Tag, Extra> Allocation { } } -pub trait AllocationExtra: ::std::fmt::Debug + Default + Clone { - /// Hook for performing extra checks on a memory read access. - /// - /// Takes read-only access to the allocation so we can keep all the memory read - /// operations take `&self`. Use a `RefCell` in `AllocExtra` if you - /// need to mutate. - #[inline] - fn memory_read( - _alloc: &Allocation, - _ptr: Pointer, - _size: Size, - ) -> EvalResult<'tcx> { - Ok(()) - } - - /// Hook for performing extra checks on a memory write access. - #[inline] - fn memory_written( - _alloc: &mut Allocation, - _ptr: Pointer, - _size: Size, - ) -> EvalResult<'tcx> { - Ok(()) - } - - /// Hook for performing extra checks on a memory deallocation. - /// `size` will be the size of the allocation. - #[inline] - fn memory_deallocated( - _alloc: &mut Allocation, - _ptr: Pointer, - _size: Size, - ) -> EvalResult<'tcx> { - Ok(()) - } -} - -impl AllocationExtra<()> for () {} - -impl Allocation { - /// Creates a read-only allocation initialized by the given bytes - pub fn from_bytes(slice: &[u8], align: Align) -> Self { - let mut undef_mask = UndefMask::new(Size::ZERO); - undef_mask.grow(Size::from_bytes(slice.len() as u64), true); - Self { - bytes: slice.to_owned(), - relocations: Relocations::new(), - undef_mask, - align, - mutability: Mutability::Immutable, - extra: Extra::default(), - } - } - - pub fn from_byte_aligned_bytes(slice: &[u8]) -> Self { - Allocation::from_bytes(slice, Align::from_bytes(1).unwrap()) - } - - pub fn undef(size: Size, align: Align) -> Self { - assert_eq!(size.bytes() as usize as u64, size.bytes()); - Allocation { - bytes: vec![0; size.bytes() as usize], - relocations: Relocations::new(), - undef_mask: UndefMask::new(size), - align, - mutability: Mutability::Mutable, - extra: Extra::default(), - } - } -} - -impl<'tcx> ::serialize::UseSpecializedDecodable for &'tcx Allocation {} - +/// Relocations #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct Relocations(SortedMap); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 1b947c276f3..25ef6ddc005 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1055,7 +1055,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Allocates a byte or string literal for `mir::interpret`, read-only pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId { // create an allocation that just contains these bytes - let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes); + let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes, ()); let alloc = self.intern_const_alloc(alloc); self.alloc_map.lock().allocate(alloc) } diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 1bc3b322717..73c0f8fff7a 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -353,6 +353,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> for CompileTimeInterpreter<'a, 'mir, 'tcx> { type MemoryKinds = !; + type MemoryExtra = (); type AllocExtra = (); type PointerTag = (); diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 57640dc48f1..481c46cb510 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -77,8 +77,13 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// The `default()` is used for pointers to consts, statics, vtables and functions. type PointerTag: ::std::fmt::Debug + Default + Copy + Eq + Hash + 'static; + /// Extra data stored in memory. A reference to this is available when `AllocExtra` + /// gets initialized, so you can e.g. have an `Rc` here if there is global state you + /// need access to in the `AllocExtra` hooks. + type MemoryExtra: Default; + /// Extra data stored in every allocation. - type AllocExtra: AllocationExtra; + type AllocExtra: AllocationExtra; /// Memory's allocation map type MemoryMap: diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index c673b57a66f..99bf93c8a9b 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -73,6 +73,9 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { /// that do not exist any more. dead_alloc_map: FxHashMap, + /// Extra data added by the machine. + pub extra: M::MemoryExtra, + /// Lets us implement `HasDataLayout`, which is awfully convenient. pub(super) tcx: TyCtxtAt<'a, 'tcx, 'tcx>, } @@ -88,13 +91,19 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> HasDataLayout // FIXME: Really we shouldn't clone memory, ever. Snapshot machinery should instead // carefully copy only the reachable parts. -impl<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> - Clone for Memory<'a, 'mir, 'tcx, M> +impl<'a, 'mir, 'tcx, M> + Clone +for + Memory<'a, 'mir, 'tcx, M> +where + M: Machine<'a, 'mir, 'tcx, PointerTag=(), AllocExtra=(), MemoryExtra=()>, + M::MemoryMap: AllocMap, Allocation)>, { fn clone(&self) -> Self { Memory { alloc_map: self.alloc_map.clone(), dead_alloc_map: self.dead_alloc_map.clone(), + extra: (), tcx: self.tcx, } } @@ -103,8 +112,9 @@ impl<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>) -> Self { Memory { - alloc_map: Default::default(), + alloc_map: M::MemoryMap::default(), dead_alloc_map: FxHashMap::default(), + extra: M::MemoryExtra::default(), tcx, } } @@ -133,7 +143,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { align: Align, kind: MemoryKind, ) -> EvalResult<'tcx, Pointer> { - Ok(Pointer::from(self.allocate_with(Allocation::undef(size, align), kind)?)) + let extra = AllocationExtra::memory_allocated(size, &self.extra)?; + Ok(Pointer::from(self.allocate_with(Allocation::undef(size, align, extra), kind)?)) } pub fn reallocate( @@ -601,7 +612,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { /// Interning (for CTFE) impl<'a, 'mir, 'tcx, M> Memory<'a, 'mir, 'tcx, M> where - M: Machine<'a, 'mir, 'tcx, PointerTag=(), AllocExtra=()>, + M: Machine<'a, 'mir, 'tcx, PointerTag=(), AllocExtra=(), MemoryExtra=()>, + // FIXME: Working around https://github.com/rust-lang/rust/issues/24159 M::MemoryMap: AllocMap, Allocation)>, { /// mark an allocation as static and initialized, either mutable or not diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 0fd1a993cbd..1b47530eaec 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -295,10 +295,12 @@ impl<'tcx, Tag: ::std::fmt::Debug> PlaceTy<'tcx, Tag> { // separating the pointer tag for `impl Trait`, see https://github.com/rust-lang/rust/issues/54385 impl<'a, 'mir, 'tcx, Tag, M> EvalContext<'a, 'mir, 'tcx, M> where + // FIXME: Working around https://github.com/rust-lang/rust/issues/54385 Tag: ::std::fmt::Debug+Default+Copy+Eq+Hash+'static, M: Machine<'a, 'mir, 'tcx, PointerTag=Tag>, + // FIXME: Working around https://github.com/rust-lang/rust/issues/24159 M::MemoryMap: AllocMap, Allocation)>, - M::AllocExtra: AllocationExtra, + M::AllocExtra: AllocationExtra, { /// Take a value, which represents a (thin or fat) reference, and make it a place. /// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`. From 6cca7165ea60d1bd8b3347a68972b9c5bcbd2d5c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 15 Nov 2018 12:03:38 +0100 Subject: [PATCH 0245/1984] pass MemoryExtra to find_foreign_static and adjust_static_allocation; they might have to create allocations --- src/librustc_mir/const_eval.rs | 10 ++++++---- src/librustc_mir/interpret/machine.rs | 10 ++++++---- src/librustc_mir/interpret/memory.rs | 14 ++++++++------ 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 73c0f8fff7a..30c06ba5659 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -433,16 +433,18 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> } fn find_foreign_static( - _tcx: TyCtxtAt<'a, 'tcx, 'tcx>, _def_id: DefId, + _tcx: TyCtxtAt<'a, 'tcx, 'tcx>, + _memory_extra: &(), ) -> EvalResult<'tcx, Cow<'tcx, Allocation>> { err!(ReadForeignStatic) } #[inline(always)] - fn adjust_static_allocation( - alloc: &'_ Allocation - ) -> Cow<'_, Allocation> { + fn adjust_static_allocation<'b>( + alloc: &'b Allocation, + _memory_extra: &(), + ) -> Cow<'b, Allocation> { // We do not use a tag so we can just cheaply forward the reference Cow::Borrowed(alloc) } diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 481c46cb510..bf260c86742 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -140,8 +140,9 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// the machine memory. (This relies on `AllocMap::get_or` being able to add the /// owned allocation to the map even when the map is shared.) fn find_foreign_static( - tcx: TyCtxtAt<'a, 'tcx, 'tcx>, def_id: DefId, + tcx: TyCtxtAt<'a, 'tcx, 'tcx>, + memory_extra: &Self::MemoryExtra, ) -> EvalResult<'tcx, Cow<'tcx, Allocation>>; /// Called to turn an allocation obtained from the `tcx` into one that has @@ -151,9 +152,10 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// allocation (because a copy had to be done to add tags or metadata), machine memory will /// cache the result. (This relies on `AllocMap::get_or` being able to add the /// owned allocation to the map even when the map is shared.) - fn adjust_static_allocation( - alloc: &'_ Allocation - ) -> Cow<'_, Allocation>; + fn adjust_static_allocation<'b>( + alloc: &'b Allocation, + memory_extra: &Self::MemoryExtra, + ) -> Cow<'b, Allocation>; /// Called for all binary operations on integer(-like) types when one operand is a pointer /// value, and for the `Offset` operation that is inherently about pointers. diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 99bf93c8a9b..b52feb41370 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -320,15 +320,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { /// this machine use the same pointer tag, so it is indirected through /// `M::static_with_default_tag`. fn get_static_alloc( - tcx: TyCtxtAt<'a, 'tcx, 'tcx>, id: AllocId, + tcx: TyCtxtAt<'a, 'tcx, 'tcx>, + memory_extra: &M::MemoryExtra, ) -> EvalResult<'tcx, Cow<'tcx, Allocation>> { let alloc = tcx.alloc_map.lock().get(id); let def_id = match alloc { Some(AllocType::Memory(mem)) => { // We got tcx memory. Let the machine figure out whether and how to // turn that into memory with the right pointer tag. - return Ok(M::adjust_static_allocation(mem)) + return Ok(M::adjust_static_allocation(mem, memory_extra)) } Some(AllocType::Function(..)) => { return err!(DerefFunctionPointer) @@ -342,7 +343,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // We got a "lazy" static that has not been computed yet, do some work trace!("static_alloc: Need to compute {:?}", def_id); if tcx.is_foreign_item(def_id) { - return M::find_foreign_static(tcx, def_id); + return M::find_foreign_static(def_id, tcx, memory_extra); } let instance = Instance::mono(tcx.tcx, def_id); let gid = GlobalId { @@ -362,7 +363,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { let allocation = tcx.alloc_map.lock().unwrap_memory(raw_const.alloc_id); // We got tcx memory. Let the machine figure out whether and how to // turn that into memory with the right pointer tag. - M::adjust_static_allocation(allocation) + M::adjust_static_allocation(allocation, memory_extra) }) } @@ -372,7 +373,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // `get_static_alloc` that we can actually use directly without inserting anything anywhere. // So the error type is `EvalResult<'tcx, &Allocation>`. let a = self.alloc_map.get_or(id, || { - let alloc = Self::get_static_alloc(self.tcx, id).map_err(Err)?; + let alloc = Self::get_static_alloc(id, self.tcx, &self.extra).map_err(Err)?; match alloc { Cow::Borrowed(alloc) => { // We got a ref, cheaply return that as an "error" so that the @@ -401,10 +402,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { id: AllocId, ) -> EvalResult<'tcx, &mut Allocation> { let tcx = self.tcx; + let memory_extra = &self.extra; let a = self.alloc_map.get_mut_or(id, || { // Need to make a copy, even if `get_static_alloc` is able // to give us a cheap reference. - let alloc = Self::get_static_alloc(tcx, id)?; + let alloc = Self::get_static_alloc(id, tcx, memory_extra)?; if alloc.mutability == Mutability::Immutable { return err!(ModifiedConstantMemory); } From 53ed3b79562fdbcbb1ca073cb48a6fea1e23d51a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 15 Nov 2018 13:25:22 +0100 Subject: [PATCH 0246/1984] make memory allocation hook infallible --- src/librustc/mir/interpret/allocation.rs | 6 +++--- src/librustc_mir/interpret/memory.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index b1e92ef4b51..d6c740794d5 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -59,7 +59,7 @@ pub trait AllocationExtra: ::std::fmt::Debug + Clone { fn memory_allocated( _size: Size, _memory_extra: &MemoryExtra - ) -> EvalResult<'tcx, Self>; + ) -> Self; /// Hook for performing extra checks on a memory read access. /// @@ -102,8 +102,8 @@ impl AllocationExtra<(), ()> for () { fn memory_allocated( _size: Size, _memory_extra: &() - ) -> EvalResult<'tcx, Self> { - Ok(()) + ) -> Self { + () } } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index b52feb41370..5c293bac74a 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -143,7 +143,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { align: Align, kind: MemoryKind, ) -> EvalResult<'tcx, Pointer> { - let extra = AllocationExtra::memory_allocated(size, &self.extra)?; + let extra = AllocationExtra::memory_allocated(size, &self.extra); Ok(Pointer::from(self.allocate_with(Allocation::undef(size, align, extra), kind)?)) } From 261faf3ce22ce930d48ecbbf872d46a613b1f0ab Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 15 Nov 2018 17:14:53 +0100 Subject: [PATCH 0247/1984] machine hooks for stack push and pop, frame machine data --- src/librustc_mir/const_eval.rs | 21 ++++++++++++++++++++- src/librustc_mir/interpret/eval_context.rs | 18 ++++++++++++------ src/librustc_mir/interpret/machine.rs | 14 ++++++++++++++ src/librustc_mir/interpret/operand.rs | 2 +- src/librustc_mir/interpret/snapshot.rs | 2 ++ 5 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 30c06ba5659..291b5c170ef 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -65,6 +65,7 @@ pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>( return_place: None, return_to_block: StackPopCleanup::Goto(None), // never pop stmt: 0, + extra: (), }); Ok(ecx) } @@ -353,9 +354,11 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> for CompileTimeInterpreter<'a, 'mir, 'tcx> { type MemoryKinds = !; + type PointerTag = (); + + type FrameExtra = (); type MemoryExtra = (); type AllocExtra = (); - type PointerTag = (); type MemoryMap = FxHashMap, Allocation)>; @@ -490,6 +493,22 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> ) -> EvalResult<'tcx, Pointer> { Ok(ptr) } + + #[inline(always)] + fn stack_push( + _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + ) -> EvalResult<'tcx> { + Ok(()) + } + + /// Called immediately before a stack frame gets popped + #[inline(always)] + fn stack_pop( + _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + _extra: (), + ) -> EvalResult<'tcx> { + Ok(()) + } } /// Project to a field of a (variant of a) const diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 2eb5f7c853f..d36d530fe78 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -49,7 +49,7 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { pub(crate) memory: Memory<'a, 'mir, 'tcx, M>, /// The virtual call stack. - pub(crate) stack: Vec>, + pub(crate) stack: Vec>, /// A cache for deduplicating vtables pub(super) vtables: FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), AllocId>, @@ -57,7 +57,7 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { /// A stack frame. #[derive(Clone)] -pub struct Frame<'mir, 'tcx: 'mir, Tag=()> { +pub struct Frame<'mir, 'tcx: 'mir, Tag=(), Extra=()> { //////////////////////////////////////////////////////////////////////////////// // Function and callsite information //////////////////////////////////////////////////////////////////////////////// @@ -96,6 +96,9 @@ pub struct Frame<'mir, 'tcx: 'mir, Tag=()> { /// The index of the currently evaluated statement. pub stmt: usize, + + /// Extra data for the machine + pub extra: Extra, } #[derive(Clone, Debug, Eq, PartialEq, Hash)] @@ -196,7 +199,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } #[inline(always)] - pub fn stack(&self) -> &[Frame<'mir, 'tcx, M::PointerTag>] { + pub fn stack(&self) -> &[Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>] { &self.stack } @@ -207,12 +210,12 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } #[inline(always)] - pub fn frame(&self) -> &Frame<'mir, 'tcx, M::PointerTag> { + pub fn frame(&self) -> &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra> { self.stack.last().expect("no call frames exist") } #[inline(always)] - pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx, M::PointerTag> { + pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra> { self.stack.last_mut().expect("no call frames exist") } @@ -294,7 +297,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc pub fn layout_of_local( &self, - frame: &Frame<'mir, 'tcx, M::PointerTag>, + frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>, local: mir::Local ) -> EvalResult<'tcx, TyLayout<'tcx>> { let local_ty = frame.mir.local_decls[local].ty; @@ -424,6 +427,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc ::log_settings::settings().indentation += 1; // first push a stack frame so we have access to the local substs + let extra = M::stack_push(self)?; self.stack.push(Frame { mir, block: mir::START_BLOCK, @@ -435,6 +439,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc span, instance, stmt: 0, + extra, }); // don't allocate at all for trivial constants @@ -504,6 +509,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc let frame = self.stack.pop().expect( "tried to pop a stack frame, but there were none", ); + M::stack_pop(self, frame.extra)?; // Abort early if we do not want to clean up: We also avoid validation in that case, // because this is CTFE and the final value will be thoroughly validated anyway. match frame.return_to_block { diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index bf260c86742..2c78807df45 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -77,6 +77,9 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// The `default()` is used for pointers to consts, statics, vtables and functions. type PointerTag: ::std::fmt::Debug + Default + Copy + Eq + Hash + 'static; + /// Extra data stored in every call frame. + type FrameExtra; + /// Extra data stored in memory. A reference to this is available when `AllocExtra` /// gets initialized, so you can e.g. have an `Rc` here if there is global state you /// need access to in the `AllocExtra` hooks. @@ -213,4 +216,15 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { ) -> EvalResult<'tcx> { Ok(()) } + + /// Called immediately before a new stack frame got pushed + fn stack_push( + ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + ) -> EvalResult<'tcx, Self::FrameExtra>; + + /// Called immediately after a stack frame gets popped + fn stack_pop( + ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + extra: Self::FrameExtra, + ) -> EvalResult<'tcx>; } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 539bc6d965f..83ceadada65 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -471,7 +471,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> /// When you know the layout of the local in advance, you can pass it as last argument pub fn access_local( &self, - frame: &super::Frame<'mir, 'tcx, M::PointerTag>, + frame: &super::Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>, local: mir::Local, layout: Option>, ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> { diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs index 4b63335ad96..f9ce7b4319f 100644 --- a/src/librustc_mir/interpret/snapshot.rs +++ b/src/librustc_mir/interpret/snapshot.rs @@ -323,6 +323,7 @@ impl_stable_hash_for!(impl<'tcx, 'mir: 'tcx> for struct Frame<'mir, 'tcx> { locals, block, stmt, + extra, }); impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx> @@ -340,6 +341,7 @@ impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx> locals, block, stmt, + extra: _, } = self; FrameSnapshot { From fb8b1e39893d009342fa4ec5e524787f56a7aea0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Nov 2018 14:05:00 +0100 Subject: [PATCH 0248/1984] accept undef in raw pointers, for consistency with integers --- src/librustc_mir/interpret/validity.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index ed4cb65ea74..d98d05bc01b 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -312,12 +312,16 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> } } ty::RawPtr(..) => { - // No undef allowed here. Eventually this should be consistent with - // the integer types. - let _ptr = try_validation!(value.to_scalar_ptr(), - "undefined address in pointer", self.path); - let _meta = try_validation!(value.to_meta(), - "uninitialized data in fat pointer metadata", self.path); + if self.const_mode { + // Integers/floats in CTFE: For consistency with integers, we do not + // accept undef. + let _ptr = try_validation!(value.to_scalar_ptr(), + "undefined address in raw pointer", self.path); + let _meta = try_validation!(value.to_meta(), + "uninitialized data in raw fat pointer metadata", self.path); + } else { + // Remain consistent with `usize`: Accept anything. + } } _ if ty.is_box() || ty.is_region_ptr() => { // Handle fat pointers. From 349271ab2c795b068dd208176fe00d9b257ab4f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?= =?UTF-8?q?e=CC=B6r=20Scherer?= Date: Tue, 20 Nov 2018 09:47:36 +0100 Subject: [PATCH 0249/1984] Typo Co-Authored-By: RalfJung --- src/librustc/mir/interpret/allocation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index d6c740794d5..c1ce11a9821 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -55,7 +55,7 @@ pub struct Allocation { pub trait AllocationExtra: ::std::fmt::Debug + Clone { - /// Hook to initialize the extra data when an allocation gets crated. + /// Hook to initialize the extra data when an allocation gets created. fn memory_allocated( _size: Size, _memory_extra: &MemoryExtra From af54eb2916b9f5707c7bfa577f5db29918870ce2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Nov 2018 10:56:10 +0100 Subject: [PATCH 0250/1984] read_c_str should call the AllocationExtra hooks --- src/librustc/mir/interpret/allocation.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index c612d6ad1bb..406d41d3436 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -172,10 +172,9 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { let offset = ptr.offset.bytes() as usize; match self.bytes[offset..].iter().position(|&c| c == 0) { Some(size) => { - let p1 = Size::from_bytes((size + 1) as u64); - self.check_relocations(cx, ptr, p1)?; - self.check_defined(ptr, p1)?; - Ok(&self.bytes[offset..offset + size]) + let size = Size::from_bytes((size + 1) as u64); + // Go through `get_bytes` for checks and AllocationExtra hooks + self.get_bytes(cx, ptr, size) } None => err!(UnterminatedCString(ptr.erase_tag())), } From 0fac350f9982b78ef5c74ac7db98933262d361b5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Nov 2018 11:23:21 +0100 Subject: [PATCH 0251/1984] yay for NLL --- src/librustc/mir/interpret/allocation.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 406d41d3436..3ff0e9f177d 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -314,11 +314,9 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { }, }; - { - let endian = cx.data_layout().endian; - let dst = self.get_bytes_mut(cx, ptr, type_size)?; - write_target_uint(endian, dst, bytes).unwrap(); - } + let endian = cx.data_layout().endian; + let dst = self.get_bytes_mut(cx, ptr, type_size)?; + write_target_uint(endian, dst, bytes).unwrap(); // See if we have to also write a relocation match val { From a6ea01f2396a55c5245b93b8f9c6edd3c5a0e204 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Nov 2018 12:07:20 +0100 Subject: [PATCH 0252/1984] fix length of slice returned from read_c_str --- src/librustc/mir/interpret/allocation.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 3ff0e9f177d..0ecec753398 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -172,9 +172,11 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { let offset = ptr.offset.bytes() as usize; match self.bytes[offset..].iter().position(|&c| c == 0) { Some(size) => { - let size = Size::from_bytes((size + 1) as u64); - // Go through `get_bytes` for checks and AllocationExtra hooks - self.get_bytes(cx, ptr, size) + let size_with_null = Size::from_bytes((size + 1) as u64); + // Go through `get_bytes` for checks and AllocationExtra hooks. + // We read the null, so we include it in the requestm, but we want it removed + // from the result! + Ok(&self.get_bytes(cx, ptr, size_with_null)?[..size]) } None => err!(UnterminatedCString(ptr.erase_tag())), } From 2472e832503995a024a6fbf533b504a0d0bf9e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?= =?UTF-8?q?e=CC=B6r=20Scherer?= Date: Sun, 25 Nov 2018 14:21:34 +0100 Subject: [PATCH 0253/1984] Typo Co-Authored-By: RalfJung --- src/librustc/mir/interpret/allocation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 0ecec753398..ab63e882c4a 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -174,7 +174,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Some(size) => { let size_with_null = Size::from_bytes((size + 1) as u64); // Go through `get_bytes` for checks and AllocationExtra hooks. - // We read the null, so we include it in the requestm, but we want it removed + // We read the null, so we include it in the request, but we want it removed // from the result! Ok(&self.get_bytes(cx, ptr, size_with_null)?[..size]) } From d4a78da543fd8959edf386602537bece057a3918 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 31 Oct 2018 00:22:19 +0300 Subject: [PATCH 0254/1984] resolve: Prohibit relative paths in visibilities on 2018 edition --- src/librustc_resolve/lib.rs | 13 ++++++++++++- src/test/ui/privacy/restricted/relative-2018.rs | 13 +++++++++++++ .../ui/privacy/restricted/relative-2018.stderr | 16 ++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/privacy/restricted/relative-2018.rs create mode 100644 src/test/ui/privacy/restricted/relative-2018.stderr diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 12dabd2a31d..a392ab717c0 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -4710,7 +4710,18 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { ty::Visibility::Restricted(self.current_module.normal_ancestor_id) } ast::VisibilityKind::Restricted { ref path, id, .. } => { - // Visibilities are resolved as global by default, add starting root segment. + // For visibilities we are not ready to provide correct implementation of "uniform + // paths" right now, so on 2018 edition we only allow module-relative paths for now. + let first_ident = path.segments[0].ident; + if self.session.rust_2018() && !first_ident.is_path_segment_keyword() { + let msg = "relative paths are not supported in visibilities on 2018 edition"; + self.session.struct_span_err(first_ident.span, msg) + .span_suggestion(path.span, "try", format!("crate::{}", path)) + .emit(); + return ty::Visibility::Public; + } + // On 2015 visibilities are resolved as crate-relative by default, + // add starting root segment if necessary. let segments = path.make_root().iter().chain(path.segments.iter()) .map(|seg| Segment { ident: seg.ident, id: Some(seg.id) }) .collect::>(); diff --git a/src/test/ui/privacy/restricted/relative-2018.rs b/src/test/ui/privacy/restricted/relative-2018.rs new file mode 100644 index 00000000000..69b7c1e4d4f --- /dev/null +++ b/src/test/ui/privacy/restricted/relative-2018.rs @@ -0,0 +1,13 @@ +// edition:2018 + +mod m { + pub(in crate) struct S1; // OK + pub(in super) struct S2; // OK + pub(in self) struct S3; // OK + pub(in ::core) struct S4; + //~^ ERROR visibilities can only be restricted to ancestor modules + pub(in a::b) struct S5; + //~^ ERROR relative paths are not supported in visibilities on 2018 edition +} + +fn main() {} diff --git a/src/test/ui/privacy/restricted/relative-2018.stderr b/src/test/ui/privacy/restricted/relative-2018.stderr new file mode 100644 index 00000000000..61effc463e9 --- /dev/null +++ b/src/test/ui/privacy/restricted/relative-2018.stderr @@ -0,0 +1,16 @@ +error: visibilities can only be restricted to ancestor modules + --> $DIR/relative-2018.rs:7:12 + | +LL | pub(in ::core) struct S4; + | ^^^^^^ + +error: relative paths are not supported in visibilities on 2018 edition + --> $DIR/relative-2018.rs:9:12 + | +LL | pub(in a::b) struct S5; + | ^--- + | | + | help: try: `crate::a::b` + +error: aborting due to 2 previous errors + From e593431bc7f3ad89aea8e792384d6719bf60f3f3 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 25 Nov 2018 04:25:59 +0300 Subject: [PATCH 0255/1984] resolve: Fix bad span arithmetics in import conflict diagnostics --- src/librustc_resolve/lib.rs | 10 +++++----- src/test/ui/issues/issue-45829/import-self.rs | 3 +++ .../ui/issues/issue-45829/import-self.stderr | 20 ++++++++++++++++--- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a392ab717c0..443b1ccdef8 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -4999,10 +4999,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { err.span_suggestion_with_applicability( binding.span, &rename_msg, - match (&directive.subclass, snippet.as_ref()) { - (ImportDirectiveSubclass::SingleImport { .. }, "self") => + match directive.subclass { + ImportDirectiveSubclass::SingleImport { type_ns_only: true, .. } => format!("self as {}", suggested_name), - (ImportDirectiveSubclass::SingleImport { source, .. }, _) => + ImportDirectiveSubclass::SingleImport { source, .. } => format!( "{} as {}{}", &snippet[..((source.span.hi().0 - binding.span.lo().0) as usize)], @@ -5013,13 +5013,13 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { "" } ), - (ImportDirectiveSubclass::ExternCrate { source, target, .. }, _) => + ImportDirectiveSubclass::ExternCrate { source, target, .. } => format!( "extern crate {} as {};", source.unwrap_or(target.name), suggested_name, ), - (_, _) => unreachable!(), + _ => unreachable!(), }, Applicability::MaybeIncorrect, ); diff --git a/src/test/ui/issues/issue-45829/import-self.rs b/src/test/ui/issues/issue-45829/import-self.rs index 8b13ffd0076..eb5fb458d82 100644 --- a/src/test/ui/issues/issue-45829/import-self.rs +++ b/src/test/ui/issues/issue-45829/import-self.rs @@ -19,4 +19,7 @@ use foo as self; use foo::self; +use foo::A; +use foo::{self as A}; + fn main() {} diff --git a/src/test/ui/issues/issue-45829/import-self.stderr b/src/test/ui/issues/issue-45829/import-self.stderr index 985dc4e7131..55e51952a88 100644 --- a/src/test/ui/issues/issue-45829/import-self.stderr +++ b/src/test/ui/issues/issue-45829/import-self.stderr @@ -25,7 +25,21 @@ help: you can use `as` to change the binding name of the import LL | use foo::{self as other_foo}; | ^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error[E0252]: the name `A` is defined multiple times + --> $DIR/import-self.rs:23:11 + | +LL | use foo::A; + | ------ previous import of the type `A` here +LL | use foo::{self as A}; + | ^^^^^^^^^ `A` reimported here + | + = note: `A` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo::{self as OtherA}; + | ^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors -Some errors occurred: E0255, E0429. -For more information about an error, try `rustc --explain E0255`. +Some errors occurred: E0252, E0255, E0429. +For more information about an error, try `rustc --explain E0252`. From fe548e311a8f3a2e193989dc959841874738423f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 25 Nov 2018 05:45:43 +0300 Subject: [PATCH 0256/1984] resolve: Fix some more asserts in import validation --- src/librustc_resolve/resolve_imports.rs | 3 +- src/test/ui/imports/auxiliary/issue-56125.rs | 2 + src/test/ui/imports/issue-56125.rs | 25 +++++++-- src/test/ui/imports/issue-56125.stderr | 59 +++++++++++++------- 4 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 616cc9d2fc5..52e3e54b9f9 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -864,7 +864,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } PathResult::NonModule(path_res) if path_res.base_def() == Def::Err => { // The error was already reported earlier. - assert!(directive.imported_module.get().is_none()); + assert!(!self.ambiguity_errors.is_empty() || + directive.imported_module.get().is_none()); return None; } PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(), diff --git a/src/test/ui/imports/auxiliary/issue-56125.rs b/src/test/ui/imports/auxiliary/issue-56125.rs index 0ff407756b3..8e079758297 100644 --- a/src/test/ui/imports/auxiliary/issue-56125.rs +++ b/src/test/ui/imports/auxiliary/issue-56125.rs @@ -1,3 +1,5 @@ +pub mod issue_56125 {} + pub mod last_segment { pub mod issue_56125 {} } diff --git a/src/test/ui/imports/issue-56125.rs b/src/test/ui/imports/issue-56125.rs index 4baeb8a34dd..843b52f1843 100644 --- a/src/test/ui/imports/issue-56125.rs +++ b/src/test/ui/imports/issue-56125.rs @@ -2,11 +2,24 @@ // compile-flags:--extern issue_56125 // aux-build:issue-56125.rs -use issue_56125::last_segment::*; -//~^ ERROR `issue_56125` is ambiguous -//~| ERROR unresolved import `issue_56125::last_segment` -use issue_56125::non_last_segment::non_last_segment::*; -//~^ ERROR `issue_56125` is ambiguous -//~| ERROR failed to resolve: could not find `non_last_segment` in `issue_56125` +#![feature(uniform_paths)] + +mod m1 { + use issue_56125::last_segment::*; + //~^ ERROR `issue_56125` is ambiguous + //~| ERROR unresolved import `issue_56125::last_segment` +} + +mod m2 { + use issue_56125::non_last_segment::non_last_segment::*; + //~^ ERROR `issue_56125` is ambiguous + //~| ERROR failed to resolve: could not find `non_last_segment` in `issue_56125` +} + +mod m3 { + mod empty {} + use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125` + use issue_56125::*; //~ ERROR `issue_56125` is ambiguous +} fn main() {} diff --git a/src/test/ui/imports/issue-56125.stderr b/src/test/ui/imports/issue-56125.stderr index 096d5be97f0..b1292ef8f78 100644 --- a/src/test/ui/imports/issue-56125.stderr +++ b/src/test/ui/imports/issue-56125.stderr @@ -1,46 +1,67 @@ error[E0433]: failed to resolve: could not find `non_last_segment` in `issue_56125` - --> $DIR/issue-56125.rs:8:18 + --> $DIR/issue-56125.rs:14:22 | -LL | use issue_56125::non_last_segment::non_last_segment::*; - | ^^^^^^^^^^^^^^^^ could not find `non_last_segment` in `issue_56125` +LL | use issue_56125::non_last_segment::non_last_segment::*; + | ^^^^^^^^^^^^^^^^ could not find `non_last_segment` in `issue_56125` error[E0432]: unresolved import `issue_56125::last_segment` - --> $DIR/issue-56125.rs:5:18 + --> $DIR/issue-56125.rs:8:22 | -LL | use issue_56125::last_segment::*; - | ^^^^^^^^^^^^ could not find `last_segment` in `issue_56125` +LL | use issue_56125::last_segment::*; + | ^^^^^^^^^^^^ could not find `last_segment` in `issue_56125` + +error[E0432]: unresolved import `empty::issue_56125` + --> $DIR/issue-56125.rs:21:9 + | +LL | use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125` + | ^^^^^^^^^^^^^^^^^^ no `issue_56125` in `m3::empty` error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution) - --> $DIR/issue-56125.rs:5:5 + --> $DIR/issue-56125.rs:8:9 | -LL | use issue_56125::last_segment::*; - | ^^^^^^^^^^^ ambiguous name +LL | use issue_56125::last_segment::*; + | ^^^^^^^^^^^ ambiguous name | = note: `issue_56125` could refer to an extern crate passed with `--extern` = help: use `::issue_56125` to refer to this extern crate unambiguously note: `issue_56125` could also refer to the module imported here - --> $DIR/issue-56125.rs:5:5 + --> $DIR/issue-56125.rs:8:9 | -LL | use issue_56125::last_segment::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | use issue_56125::last_segment::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use `self::issue_56125` to refer to this module unambiguously error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution) - --> $DIR/issue-56125.rs:8:5 + --> $DIR/issue-56125.rs:14:9 | -LL | use issue_56125::non_last_segment::non_last_segment::*; - | ^^^^^^^^^^^ ambiguous name +LL | use issue_56125::non_last_segment::non_last_segment::*; + | ^^^^^^^^^^^ ambiguous name | = note: `issue_56125` could refer to an extern crate passed with `--extern` = help: use `::issue_56125` to refer to this extern crate unambiguously note: `issue_56125` could also refer to the module imported here - --> $DIR/issue-56125.rs:5:5 + --> $DIR/issue-56125.rs:14:9 | -LL | use issue_56125::last_segment::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | use issue_56125::non_last_segment::non_last_segment::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use `self::issue_56125` to refer to this module unambiguously -error: aborting due to 4 previous errors +error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution) + --> $DIR/issue-56125.rs:22:9 + | +LL | use issue_56125::*; //~ ERROR `issue_56125` is ambiguous + | ^^^^^^^^^^^ ambiguous name + | + = note: `issue_56125` could refer to an extern crate passed with `--extern` + = help: use `::issue_56125` to refer to this extern crate unambiguously +note: `issue_56125` could also refer to the unresolved item imported here + --> $DIR/issue-56125.rs:21:9 + | +LL | use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125` + | ^^^^^^^^^^^^^^^^^^ + = help: use `self::issue_56125` to refer to this unresolved item unambiguously + +error: aborting due to 6 previous errors Some errors occurred: E0432, E0433, E0659. For more information about an error, try `rustc --explain E0432`. From 1798d51da67835618079f034d0b552be342af5d2 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 25 Nov 2018 11:35:38 -0500 Subject: [PATCH 0257/1984] Add grammar for {f32,f64}::from_str, mention known bug. - Original bug about documenting grammar - https://github.com/rust-lang/rust/issues/32243 - Known bug with parsing - https://github.com/rust-lang/rust/issues/31407 --- src/libcore/num/dec2flt/mod.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index f93564c2849..64ac69946d1 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -122,11 +122,35 @@ macro_rules! from_str_float_impl { /// * '2.5E10', or equivalently, '2.5e10' /// * '2.5E-10' /// * '5.' - /// * '.5', or, equivalently, '0.5' + /// * '.5', or, equivalently, '0.5' /// * 'inf', '-inf', 'NaN' /// /// Leading and trailing whitespace represent an error. /// + /// # Grammar + /// + /// All strings that adhere to the following regular expression + /// will result in an [`Ok`] being returned: + /// + /// ```txt + /// (\+|-)? + /// (inf| + /// NaN| + /// ([0-9]+| + /// [0-9]+\.[0-9]*| + /// [0-9]*\.[0-9]+) + /// ((e|E) + /// (\+|-)? + /// [0-9]+)?) + /// ``` + /// + /// # Known bugs + /// + /// * [#31407]: Some strings that adhere to the regular expression + /// above will incorrectly return an [`Err`]. + /// + /// [#31407]: https://github.com/rust-lang/rust/issues/31407 + /// /// # Arguments /// /// * src - A string From 07b97a486f3580f9b50404a4199271f70b4a63fb Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Sun, 25 Nov 2018 19:31:35 +0000 Subject: [PATCH 0258/1984] Use a reference rather than take ownership --- src/libcore/num/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 71617347e4c..56ccea19b8a 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4800,7 +4800,7 @@ impl ParseIntError { reason = "it can be useful to match errors when making error messages \ for integer parsing", issue = "22639")] - pub fn kind(self) -> IntErrorKind { + pub fn kind(&self) -> &IntErrorKind { self.kind } #[unstable(feature = "int_error_internals", From 121e5e806e41c4825fc4a25ad45d2585d1058165 Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Sun, 25 Nov 2018 19:44:09 +0000 Subject: [PATCH 0259/1984] fix missing borrow --- src/libcore/num/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 56ccea19b8a..eb8a51b18a5 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4801,7 +4801,7 @@ impl ParseIntError { for integer parsing", issue = "22639")] pub fn kind(&self) -> &IntErrorKind { - self.kind + &self.kind } #[unstable(feature = "int_error_internals", reason = "available through Error trait and this method should \ From 79ee8f329d1d3105555fd40be5b0eac56c9a8e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 25 Nov 2018 12:41:38 -0800 Subject: [PATCH 0260/1984] Suggest appropriate place for lifetime when declared after type arguments --- src/libsyntax/parse/parser.rs | 43 +++++++++++++++---- src/test/ui/parser/issue-14303-enum.stderr | 4 ++ src/test/ui/parser/issue-14303-fn-def.stderr | 4 ++ src/test/ui/parser/issue-14303-impl.stderr | 4 ++ src/test/ui/parser/issue-14303-struct.stderr | 4 ++ src/test/ui/parser/issue-14303-trait.stderr | 4 ++ .../ui/suggestions/suggest-move-lifetimes.rs | 15 +++++++ .../suggestions/suggest-move-lifetimes.stderr | 32 ++++++++++++++ 8 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/suggestions/suggest-move-lifetimes.rs create mode 100644 src/test/ui/suggestions/suggest-move-lifetimes.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e2f09affd4f..07e13ffc314 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5178,8 +5178,10 @@ impl<'a> Parser<'a> { /// Parses (possibly empty) list of lifetime and type parameters, possibly including /// trailing comma and erroneous trailing attributes. crate fn parse_generic_params(&mut self) -> PResult<'a, Vec> { + let mut lifetimes = Vec::new(); let mut params = Vec::new(); - let mut seen_ty_param = false; + let mut seen_ty_param: Option = None; + let mut last_comma_span = None; loop { let attrs = self.parse_outer_attributes()?; if self.check_lifetime() { @@ -5190,25 +5192,48 @@ impl<'a> Parser<'a> { } else { Vec::new() }; - params.push(ast::GenericParam { + lifetimes.push(ast::GenericParam { ident: lifetime.ident, id: lifetime.id, attrs: attrs.into(), bounds, kind: ast::GenericParamKind::Lifetime, }); - if seen_ty_param { - self.span_err(self.prev_span, - "lifetime parameters must be declared prior to type parameters"); + if let Some(sp) = seen_ty_param { + let param_span = self.prev_span; + let ate_comma = self.eat(&token::Comma); + let remove_sp = if ate_comma { + param_span.until(self.span) + } else { + last_comma_span.unwrap_or(param_span).to(param_span) + }; + let mut err = self.struct_span_err( + self.prev_span, + "lifetime parameters must be declared prior to type parameters", + ); + if let Ok(snippet) = self.sess.source_map().span_to_snippet(param_span) { + err.multipart_suggestion( + "move the lifetime parameter prior to the first type parameter", + vec![ + (remove_sp, String::new()), + (sp.shrink_to_lo(), format!("{}, ", snippet)), + ], + ); + } + err.emit(); + if ate_comma { + last_comma_span = Some(self.prev_span); + continue + } } } else if self.check_ident() { // Parse type parameter. params.push(self.parse_ty_param(attrs)?); - seen_ty_param = true; + seen_ty_param = Some(self.prev_span); } else { // Check for trailing attributes and stop parsing. if !attrs.is_empty() { - let param_kind = if seen_ty_param { "type" } else { "lifetime" }; + let param_kind = if seen_ty_param.is_some() { "type" } else { "lifetime" }; self.span_err(attrs[0].span, &format!("trailing attribute after {} parameters", param_kind)); } @@ -5218,8 +5243,10 @@ impl<'a> Parser<'a> { if !self.eat(&token::Comma) { break } + last_comma_span = Some(self.prev_span); } - Ok(params) + lifetimes.extend(params); // ensure the correct order of lifetimes and type params + Ok(lifetimes) } /// Parse a set of optional generic type parameter declarations. Where diff --git a/src/test/ui/parser/issue-14303-enum.stderr b/src/test/ui/parser/issue-14303-enum.stderr index 7d546cb2180..622066a94f8 100644 --- a/src/test/ui/parser/issue-14303-enum.stderr +++ b/src/test/ui/parser/issue-14303-enum.stderr @@ -3,6 +3,10 @@ error: lifetime parameters must be declared prior to type parameters | LL | enum X<'a, T, 'b> { | ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | enum X<'a, 'b, T> { + | ^^^ -- error: aborting due to previous error diff --git a/src/test/ui/parser/issue-14303-fn-def.stderr b/src/test/ui/parser/issue-14303-fn-def.stderr index c7b57f36376..630c9cb40de 100644 --- a/src/test/ui/parser/issue-14303-fn-def.stderr +++ b/src/test/ui/parser/issue-14303-fn-def.stderr @@ -3,6 +3,10 @@ error: lifetime parameters must be declared prior to type parameters | LL | fn foo<'a, T, 'b>(x: &'a T) {} | ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | fn foo<'a, 'b, T>(x: &'a T) {} + | ^^^ -- error: aborting due to previous error diff --git a/src/test/ui/parser/issue-14303-impl.stderr b/src/test/ui/parser/issue-14303-impl.stderr index 0b7016eb7f7..2e3181de902 100644 --- a/src/test/ui/parser/issue-14303-impl.stderr +++ b/src/test/ui/parser/issue-14303-impl.stderr @@ -3,6 +3,10 @@ error: lifetime parameters must be declared prior to type parameters | LL | impl<'a, T, 'b> X {} | ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | impl<'a, 'b, T> X {} + | ^^^ -- error: aborting due to previous error diff --git a/src/test/ui/parser/issue-14303-struct.stderr b/src/test/ui/parser/issue-14303-struct.stderr index 4a4b6789194..c6b33120c18 100644 --- a/src/test/ui/parser/issue-14303-struct.stderr +++ b/src/test/ui/parser/issue-14303-struct.stderr @@ -3,6 +3,10 @@ error: lifetime parameters must be declared prior to type parameters | LL | struct X<'a, T, 'b> { | ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | struct X<'a, 'b, T> { + | ^^^ -- error: aborting due to previous error diff --git a/src/test/ui/parser/issue-14303-trait.stderr b/src/test/ui/parser/issue-14303-trait.stderr index ab5cc5655bb..6d00f284bbb 100644 --- a/src/test/ui/parser/issue-14303-trait.stderr +++ b/src/test/ui/parser/issue-14303-trait.stderr @@ -3,6 +3,10 @@ error: lifetime parameters must be declared prior to type parameters | LL | trait Foo<'a, T, 'b> {} | ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | trait Foo<'a, 'b, T> {} + | ^^^ -- error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.rs b/src/test/ui/suggestions/suggest-move-lifetimes.rs new file mode 100644 index 00000000000..be6d29d9337 --- /dev/null +++ b/src/test/ui/suggestions/suggest-move-lifetimes.rs @@ -0,0 +1,15 @@ +struct A { + t: &'a T, +} + +struct B { + t: &'a T, + u: U, +} + +struct C { + t: &'a T, + u: U, +} + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr new file mode 100644 index 00000000000..57e6780b359 --- /dev/null +++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr @@ -0,0 +1,32 @@ +error: lifetime parameters must be declared prior to type parameters + --> $DIR/suggest-move-lifetimes.rs:1:13 + | +LL | struct A { + | ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | struct A<'a, T> { + | ^^^ -- + +error: lifetime parameters must be declared prior to type parameters + --> $DIR/suggest-move-lifetimes.rs:5:15 + | +LL | struct B { + | ^ +help: move the lifetime parameter prior to the first type parameter + | +LL | struct B<'a, T, U> { + | ^^^ -- + +error: lifetime parameters must be declared prior to type parameters + --> $DIR/suggest-move-lifetimes.rs:10:16 + | +LL | struct C { + | ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | struct C { + | ^^^ -- + +error: aborting due to 3 previous errors + From 234d043d18175aff37200a91df2a1b7c3064fc80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 25 Nov 2018 12:46:42 -0800 Subject: [PATCH 0261/1984] Move lifetimes before the *first* type argument --- src/libsyntax/parse/parser.rs | 4 +++- src/test/ui/suggestions/suggest-move-lifetimes.stderr | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 07e13ffc314..1fdf86d4867 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5229,7 +5229,9 @@ impl<'a> Parser<'a> { } else if self.check_ident() { // Parse type parameter. params.push(self.parse_ty_param(attrs)?); - seen_ty_param = Some(self.prev_span); + if seen_ty_param.is_none() { + seen_ty_param = Some(self.prev_span); + } } else { // Check for trailing attributes and stop parsing. if !attrs.is_empty() { diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr index 57e6780b359..fa1cfe66ab5 100644 --- a/src/test/ui/suggestions/suggest-move-lifetimes.stderr +++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr @@ -25,8 +25,8 @@ LL | struct C { | ^^ help: move the lifetime parameter prior to the first type parameter | -LL | struct C { - | ^^^ -- +LL | struct C<'a, T, U> { + | ^^^ -- error: aborting due to 3 previous errors From e281446261b1d5c7f44926a3c946156a05388d5f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 24 Nov 2018 09:31:01 +0200 Subject: [PATCH 0262/1984] Try to make top-level Cargo.toml work without __CARGO_TEST_ROOT. --- src/bootstrap/test.rs | 1 - src/bootstrap/tool.rs | 20 ++----------------- .../run-make/thumb-none-cortex-m/Makefile | 5 ++++- src/test/run-make/thumb-none-qemu/script.sh | 7 +++++-- 4 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index c50e6a27033..e55773011df 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1934,7 +1934,6 @@ impl Step for Distcheck { .arg("generate-lockfile") .arg("--manifest-path") .arg(&toml) - .env("__CARGO_TEST_ROOT", &dir) .current_dir(&dir), ); } diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 4acc739db57..58c5296beb3 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -264,7 +264,6 @@ macro_rules! tool { $name:ident, $path:expr, $tool_name:expr, $mode:expr $(,llvm_tools = $llvm:expr)* $(,is_external_tool = $external:expr)* - $(,cargo_test_root = $cargo_test_root:expr)* ; )+) => { #[derive(Copy, PartialEq, Eq, Clone)] @@ -288,15 +287,6 @@ macro_rules! tool { $(Tool::$name => false $(|| $llvm)*,)+ } } - - /// Whether this tool requires may run Cargo for test crates, - /// which currently needs setting the environment variable - /// `__CARGO_TEST_ROOT` to separate it from the workspace. - pub fn needs_cargo_test_root(&self) -> bool { - match self { - $(Tool::$name => false $(|| $cargo_test_root)*,)+ - } - } } impl<'a> Builder<'a> { @@ -372,9 +362,8 @@ tool!( UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::ToolBootstrap; Tidy, "src/tools/tidy", "tidy", Mode::ToolBootstrap; Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::ToolBootstrap; - CargoTest, "src/tools/cargotest", "cargotest", Mode::ToolBootstrap, cargo_test_root = true; - Compiletest, "src/tools/compiletest", "compiletest", Mode::ToolBootstrap, - llvm_tools = true, cargo_test_root = true; + CargoTest, "src/tools/cargotest", "cargotest", Mode::ToolBootstrap; + Compiletest, "src/tools/compiletest", "compiletest", Mode::ToolBootstrap, llvm_tools = true; BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::ToolBootstrap; RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::ToolBootstrap; RustInstaller, "src/tools/rust-installer", "fabricate", Mode::ToolBootstrap, @@ -693,11 +682,6 @@ impl<'a> Builder<'a> { } } - // Set `__CARGO_TEST_ROOT` to the build directory if needed. - if tool.needs_cargo_test_root() { - cmd.env("__CARGO_TEST_ROOT", &self.config.out); - } - add_lib_path(lib_paths, cmd); } diff --git a/src/test/run-make/thumb-none-cortex-m/Makefile b/src/test/run-make/thumb-none-cortex-m/Makefile index 741bce921e6..819439069ea 100644 --- a/src/test/run-make/thumb-none-cortex-m/Makefile +++ b/src/test/run-make/thumb-none-cortex-m/Makefile @@ -32,7 +32,10 @@ all: mkdir -p $(WORK_DIR) -cd $(WORK_DIR) && rm -rf $(CRATE) cd $(WORK_DIR) && bash -x $(HERE)/../git_clone_sha1.sh $(CRATE) $(CRATE_URL) $(CRATE_SHA1) - cd $(WORK_DIR) && cd $(CRATE) && $(CARGO) build --target $(TARGET) -v + # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features. + # These come from the top-level Rust workspace, that this crate is not a + # member of, but Cargo tries to load the workspace `Cargo.toml` anyway. + cd $(WORK_DIR) && cd $(CRATE) && env RUSTC_BOOTSTRAP=1 $(CARGO) build --target $(TARGET) -v else all: diff --git a/src/test/run-make/thumb-none-qemu/script.sh b/src/test/run-make/thumb-none-qemu/script.sh index 0f1c49f3a71..c5cbff5c3c3 100644 --- a/src/test/run-make/thumb-none-qemu/script.sh +++ b/src/test/run-make/thumb-none-qemu/script.sh @@ -8,9 +8,12 @@ pushd $WORK_DIR rm -rf $CRATE || echo OK cp -a $HERE/example . pushd $CRATE - env RUSTFLAGS="-C linker=arm-none-eabi-ld -C link-arg=-Tlink.x" \ + # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features. + # These come from the top-level Rust workspace, that this crate is not a + # member of, but Cargo tries to load the workspace `Cargo.toml` anyway. + env RUSTC_BOOTSTRAP=1 RUSTFLAGS="-C linker=arm-none-eabi-ld -C link-arg=-Tlink.x" \ $CARGO run --target $TARGET | grep "x = 42" - env RUSTFLAGS="-C linker=arm-none-eabi-ld -C link-arg=-Tlink.x" \ + env RUSTC_BOOTSTRAP=1 RUSTFLAGS="-C linker=arm-none-eabi-ld -C link-arg=-Tlink.x" \ $CARGO run --target $TARGET --release | grep "x = 42" popd popd From d9ca24e87048f506b394b35f9013af9fd6764877 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 25 Nov 2018 14:59:52 +0200 Subject: [PATCH 0263/1984] Cargo.toml: exclude the `build` directory from the workspace. --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 1e1d7a40967..874f5cb9680 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ members = [ ] exclude = [ "src/tools/rls/test_data", + "build", ] # Curiously, LLVM 7.0 will segfault if compiled with opt-level=3 From 6aa4eb923f83112867a043726d04b81107bb9241 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 25 Nov 2018 23:15:20 +0200 Subject: [PATCH 0264/1984] HACK(eddyb) Cargo.toml: also exclude the `obj` directory from the workspace. --- Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 874f5cb9680..89cf687a246 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,8 @@ members = [ exclude = [ "src/tools/rls/test_data", "build", + # HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`. + "obj", ] # Curiously, LLVM 7.0 will segfault if compiled with opt-level=3 From 057e6d3a35a54e8b88c2cef1e6a1b9e590066276 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sun, 25 Nov 2018 17:33:16 +0100 Subject: [PATCH 0265/1984] Add TryFrom<&[T]> for [T; $N] where T: Copy `TryFrom<&[T]> for &[T; $N]` (note *reference* to an array) already exists, but not needing to dereference makes type inference easier for example when using `u32::from_be_bytes`. Also add doc examples doing just that. --- src/libcore/array.rs | 9 +++++ src/libcore/num/mod.rs | 78 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 3d24f8902bd..26e7a79d35d 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -148,6 +148,15 @@ macro_rules! array_impls { } } + #[unstable(feature = "try_from", issue = "33417")] + impl<'a, T> TryFrom<&'a [T]> for [T; $N] where T: Copy { + type Error = TryFromSliceError; + + fn try_from(slice: &[T]) -> Result<[T; $N], TryFromSliceError> { + <&Self>::try_from(slice).map(|r| *r) + } + } + #[unstable(feature = "try_from", issue = "33417")] impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] { type Error = TryFromSliceError; diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 9deae124829..f6f649bc06d 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1989,6 +1989,19 @@ big endian. ``` let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, "); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -2008,6 +2021,19 @@ little endian. ``` let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, "); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -2037,6 +2063,19 @@ let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"bi ", $le_bytes, " }); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -3719,6 +3758,19 @@ big endian. ``` let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, "); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -3738,6 +3790,19 @@ little endian. ``` let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, "); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] @@ -3767,6 +3832,19 @@ let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"bi ", $le_bytes, " }); assert_eq!(value, ", $swap_op, "); +``` + +When starting from a slice rather than an array, fallible conversion APIs can be used: + +``` +#![feature(try_from)] +use std::convert::TryInto; + +fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " { + let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">()); + *input = rest; + ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap()) +} ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_unstable(feature = "const_int_conversion")] From 2d2b7c01ebee3f2926af58b9461284e271955855 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 25 Nov 2018 15:43:00 -0700 Subject: [PATCH 0266/1984] Make JSON output from -Zprofile-json valid --- src/librustc/util/profiling.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/util/profiling.rs b/src/librustc/util/profiling.rs index 6540a09d877..bea3453b31a 100644 --- a/src/librustc/util/profiling.rs +++ b/src/librustc/util/profiling.rs @@ -102,7 +102,7 @@ macro_rules! define_categories { }; json.push_str(&format!( - "{{ \"category\": {}, \"time_ms\": {}, + "{{ \"category\": \"{}\", \"time_ms\": {},\ \"query_count\": {}, \"query_hits\": {} }},", stringify!($name), self.times.$name / 1_000_000, From 7be0b23b691479236580ce4b601f84da2bfe9e94 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 9 Nov 2018 12:54:04 -0800 Subject: [PATCH 0267/1984] Upgrade to LLVM trunk --- src/libcompiler_builtins | 2 +- src/llvm | 2 +- src/tools/lld | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins index 939cbca6e9d..fe74674f6e4 160000 --- a/src/libcompiler_builtins +++ b/src/libcompiler_builtins @@ -1 +1 @@ -Subproject commit 939cbca6e9d829265d6cf006d3532142a4061cd3 +Subproject commit fe74674f6e4be76d47b66f67d529ebf4186f4eb1 diff --git a/src/llvm b/src/llvm index 7051ead40a5..21a0c9ebc28 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 7051ead40a5f825878b59bf08d4e768be9e99a4a +Subproject commit 21a0c9ebc285d794a298e97717abad8d6135fa87 diff --git a/src/tools/lld b/src/tools/lld index 2a9b88b8b41..1928c5eeb61 160000 --- a/src/tools/lld +++ b/src/tools/lld @@ -1 +1 @@ -Subproject commit 2a9b88b8b419d094fb2185c0ca31c28d31bdca00 +Subproject commit 1928c5eeb613a4c6d232fc47ae91914bbfd92a79 From ae5b350d7757a70e53219bbb5e32ae149ad063e0 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 9 Nov 2018 13:09:32 -0800 Subject: [PATCH 0268/1984] Handle some renamed ThinLTO functions --- src/rustllvm/PassWrapper.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 3b0046222a9..06de0d6509b 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -922,7 +922,11 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, GlobalValue::LinkageTypes NewLinkage) { ResolvedODR[ModuleIdentifier][GUID] = NewLinkage; }; +#if LLVM_VERSION_GE(8, 0) + thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage); +#else thinLTOResolveWeakForLinkerInIndex(Ret->Index, isPrevailing, recordNewLinkage); +#endif // Here we calculate an `ExportedGUIDs` set for use in the `isExported` // callback below. This callback below will dictate the linkage for all @@ -977,7 +981,11 @@ extern "C" bool LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { Module &Mod = *unwrap(M); const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier()); +#if LLVM_VERSION_GE(8, 0) + thinLTOResolvePrevailingInModule(Mod, DefinedGlobals); +#else thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals); +#endif return true; } From a43a7a07785fdaca7c04ae2ba2f29512dcca58f4 Mon Sep 17 00:00:00 2001 From: Edd Barrett Date: Wed, 7 Nov 2018 12:05:54 +0000 Subject: [PATCH 0269/1984] Make Rustc build with LLVM trunk. --- src/rustllvm/RustWrapper.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index f423503e19f..8f7db9e768b 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -705,10 +705,17 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( FPVal->getValueAPF().bitcastToAPInt().getZExtValue()); } +#if LLVM_VERSION_GE(8, 0) + llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression( + unwrapDI(Context), Name, LinkageName, + unwrapDI(File), LineNo, unwrapDI(Ty), IsLocalToUnit, + InitExpr, unwrapDIPtr(Decl), nullptr, AlignInBits); +#else llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression( unwrapDI(Context), Name, LinkageName, unwrapDI(File), LineNo, unwrapDI(Ty), IsLocalToUnit, InitExpr, unwrapDIPtr(Decl), AlignInBits); +#endif InitVal->setMetadata("dbg", VarExpr); From bf01bcb451d20d770091acb5cde4a024d91a0740 Mon Sep 17 00:00:00 2001 From: Edd Barrett Date: Wed, 7 Nov 2018 12:34:43 +0000 Subject: [PATCH 0270/1984] Conditionally compile in only the extra argument. --- src/rustllvm/RustWrapper.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 8f7db9e768b..b6e07942f86 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -705,17 +705,14 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( FPVal->getValueAPF().bitcastToAPInt().getZExtValue()); } -#if LLVM_VERSION_GE(8, 0) - llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression( - unwrapDI(Context), Name, LinkageName, - unwrapDI(File), LineNo, unwrapDI(Ty), IsLocalToUnit, - InitExpr, unwrapDIPtr(Decl), nullptr, AlignInBits); -#else llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression( unwrapDI(Context), Name, LinkageName, unwrapDI(File), LineNo, unwrapDI(Ty), IsLocalToUnit, - InitExpr, unwrapDIPtr(Decl), AlignInBits); + InitExpr, unwrapDIPtr(Decl), +#if LLVM_VERSION_GE(8, 0) + /* templateParams */ nullptr, #endif + AlignInBits); InitVal->setMetadata("dbg", VarExpr); From c86b1529a5d2141bd61586f9464bcec665830231 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 9 Nov 2018 13:51:00 -0800 Subject: [PATCH 0271/1984] wasm: Pass `--no-demangle` to LLD Our mangling scheme is not C++'s, so tell LLD to not demangle anything so we can handle Rust-specific demangling ourselves. --- src/librustc_codegen_ssa/back/linker.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index ec5ca580104..7e1ea4655fe 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -1037,6 +1037,11 @@ impl<'a> Linker for WasmLd<'a> { // indicative of bugs, let's prevent them. self.cmd.arg("--fatal-warnings"); + // LLD only implements C++-like demangling, which doesn't match our own + // mangling scheme. Tell LLD to not demangle anything and leave it up to + // us to demangle these symbols later. + self.cmd.arg("--no-demangle"); + ::std::mem::replace(&mut self.cmd, Command::new("")) } From cc9c91d3858332766b7b7aa534fa4d6e2431d4a5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 10 Nov 2018 10:04:17 -0800 Subject: [PATCH 0272/1984] Pass `--export-dynamic` to LLD for wasm This should handle recent symbol visibility changes happening, although we'll likely want to tweak this in the future! --- src/librustc_codegen_ssa/back/linker.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index 7e1ea4655fe..f3cc344254f 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -1037,6 +1037,12 @@ impl<'a> Linker for WasmLd<'a> { // indicative of bugs, let's prevent them. self.cmd.arg("--fatal-warnings"); + // The symbol visibility story is a bit in flux right now with LLD. + // It's... not entirely clear to me what's going on, but this looks to + // make everything work when `export_symbols` isn't otherwise called for + // things like executables. + self.cmd.arg("--export-dynamic"); + // LLD only implements C++-like demangling, which doesn't match our own // mangling scheme. Tell LLD to not demangle anything and leave it up to // us to demangle these symbols later. From 7215963e56321c5e92b9c2f7c4ad788362451b37 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 25 Nov 2018 20:28:26 -0800 Subject: [PATCH 0273/1984] Temporarily disable LLDB --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 14fb17aeedd..fa66220f442 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ matrix: - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler --enable-lldb --set rust.jemalloc" + RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler --set rust.jemalloc" SRC=. DEPLOY_ALT=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 @@ -87,7 +87,7 @@ matrix: # OSX 10.7 and `xcode7` is the latest Xcode able to compile LLVM for 10.7. - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc" + RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler --set rust.jemalloc" SRC=. DEPLOY=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 @@ -102,7 +102,7 @@ matrix: - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --enable-lldb --set rust.jemalloc" + RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc" SRC=. DEPLOY=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 From cc466851bc458219121142ae75f5cc47bb3a927f Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 26 Nov 2018 08:40:34 -0500 Subject: [PATCH 0274/1984] Remove unsafe `unsafe` inner function. Within this `Iterator` implementation, a function `unsafe_get` is defined which unsafely allows _unchecked_ indexing of any element in a slice. This should be marked as _unsafe_, but it is not. To address this issue, I removed that inner function. --- src/libcore/str/lossy.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/libcore/str/lossy.rs b/src/libcore/str/lossy.rs index 186d6adbc91..52abd8f9952 100644 --- a/src/libcore/str/lossy.rs +++ b/src/libcore/str/lossy.rs @@ -62,18 +62,15 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> { } const TAG_CONT_U8: u8 = 128; - fn unsafe_get(xs: &[u8], i: usize) -> u8 { - unsafe { *xs.get_unchecked(i) } - } fn safe_get(xs: &[u8], i: usize) -> u8 { - if i >= xs.len() { 0 } else { unsafe_get(xs, i) } + *xs.get(i).unwrap_or(&0) } let mut i = 0; while i < self.source.len() { let i_ = i; - let byte = unsafe_get(self.source, i); + let byte = unsafe { *self.source.get_unchecked(i) }; i += 1; if byte < 128 { From 1a8f908126151ce9dd93f5a85d12edf3909fb839 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 26 Nov 2018 17:22:56 +0100 Subject: [PATCH 0275/1984] Add missing link in docs --- src/libcore/iter/iterator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 2903c370df8..6662d56393c 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -161,7 +161,7 @@ pub trait Iterator { /// That said, the implementation should provide a correct estimation, /// because otherwise it would be a violation of the trait's protocol. /// - /// The default implementation returns `(0, None)` which is correct for any + /// The default implementation returns `(0, `[`None`]`)` which is correct for any /// iterator. /// /// [`usize`]: ../../std/primitive.usize.html From 45dfe43887fee6c2ce4cbc3e46b31626330be094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 26 Nov 2018 08:32:47 -0800 Subject: [PATCH 0276/1984] Emit one diagnostic for multiple misplaced lifetimes --- src/libsyntax/parse/parser.rs | 31 ++++++++++++------- .../ui/suggestions/suggest-move-lifetimes.rs | 6 ++++ .../suggestions/suggest-move-lifetimes.stderr | 16 ++++++++-- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1fdf86d4867..ab5afaf3d99 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5182,6 +5182,8 @@ impl<'a> Parser<'a> { let mut params = Vec::new(); let mut seen_ty_param: Option = None; let mut last_comma_span = None; + let mut bad_lifetime_pos = vec![]; + let mut suggestions = vec![]; loop { let attrs = self.parse_outer_attributes()?; if self.check_lifetime() { @@ -5207,20 +5209,12 @@ impl<'a> Parser<'a> { } else { last_comma_span.unwrap_or(param_span).to(param_span) }; - let mut err = self.struct_span_err( - self.prev_span, - "lifetime parameters must be declared prior to type parameters", - ); + bad_lifetime_pos.push(param_span); + if let Ok(snippet) = self.sess.source_map().span_to_snippet(param_span) { - err.multipart_suggestion( - "move the lifetime parameter prior to the first type parameter", - vec![ - (remove_sp, String::new()), - (sp.shrink_to_lo(), format!("{}, ", snippet)), - ], - ); + suggestions.push((remove_sp, String::new())); + suggestions.push((sp.shrink_to_lo(), format!("{}, ", snippet))); } - err.emit(); if ate_comma { last_comma_span = Some(self.prev_span); continue @@ -5247,6 +5241,19 @@ impl<'a> Parser<'a> { } last_comma_span = Some(self.prev_span); } + if !bad_lifetime_pos.is_empty() { + let mut err = self.struct_span_err( + bad_lifetime_pos, + "lifetime parameters must be declared prior to type parameters", + ); + if !suggestions.is_empty() { + err.multipart_suggestion( + "move the lifetime parameter prior to the first type parameter", + suggestions, + ); + } + err.emit(); + } lifetimes.extend(params); // ensure the correct order of lifetimes and type params Ok(lifetimes) } diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.rs b/src/test/ui/suggestions/suggest-move-lifetimes.rs index be6d29d9337..5051a406078 100644 --- a/src/test/ui/suggestions/suggest-move-lifetimes.rs +++ b/src/test/ui/suggestions/suggest-move-lifetimes.rs @@ -12,4 +12,10 @@ struct C { u: U, } +struct D { + t: &'a T, + u: &'b U, + v: &'c V, +} + fn main() {} diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr index fa1cfe66ab5..f3d6469b512 100644 --- a/src/test/ui/suggestions/suggest-move-lifetimes.stderr +++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr @@ -9,10 +9,10 @@ LL | struct A<'a, T> { | ^^^ -- error: lifetime parameters must be declared prior to type parameters - --> $DIR/suggest-move-lifetimes.rs:5:15 + --> $DIR/suggest-move-lifetimes.rs:5:13 | LL | struct B { - | ^ + | ^^ help: move the lifetime parameter prior to the first type parameter | LL | struct B<'a, T, U> { @@ -28,5 +28,15 @@ help: move the lifetime parameter prior to the first type parameter LL | struct C<'a, T, U> { | ^^^ -- -error: aborting due to 3 previous errors +error: lifetime parameters must be declared prior to type parameters + --> $DIR/suggest-move-lifetimes.rs:15:16 + | +LL | struct D { + | ^^ ^^ ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | struct D<'a, 'b, 'c, T, U, V> { + | ^^^ ^^^ ^^^ --- + +error: aborting due to 4 previous errors From 769d7115fed078c93f66d8db24de2046a6ab6334 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Wed, 14 Nov 2018 14:51:28 -0500 Subject: [PATCH 0277/1984] add test for issue #21335 Fixes #21335. --- src/test/run-make/llvm-outputs/Makefile | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/test/run-make/llvm-outputs/Makefile diff --git a/src/test/run-make/llvm-outputs/Makefile b/src/test/run-make/llvm-outputs/Makefile new file mode 100644 index 00000000000..d7f67577b04 --- /dev/null +++ b/src/test/run-make/llvm-outputs/Makefile @@ -0,0 +1,5 @@ +-include ../../run-make-fulldeps/tools.mk + +all: + echo 'fn main() {}' | $(BARE_RUSTC) - --out-dir=$(TMPDIR)/random_directory_that_does_not_exist_ir/ --emit=llvm-ir + echo 'fn main() {}' | $(BARE_RUSTC) - --out-dir=$(TMPDIR)/random_directory_that_does_not_exist_bc/ --emit=llvm-bc From 47b5e23e6b72183b993584dc41c51652eb6adb3a Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 26 Nov 2018 18:36:03 +0000 Subject: [PATCH 0278/1984] Introduce ptr::hash for references --- src/libcore/ptr.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index e9cf11424ca..6b4ee66bb02 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2509,6 +2509,29 @@ pub fn eq(a: *const T, b: *const T) -> bool { a == b } +/// Hash the raw pointer address behind a reference, rather than the value +/// it points to. +/// +/// # Examples +/// +/// ``` +/// use std::collections::hash_map::DefaultHasher; +/// use std::hash::Hasher; +/// use std::ptr; +/// +/// let five = 5; +/// let five_ref = &five; +/// +/// let mut hasher = DefaultHasher::new(); +/// ptr::hash(five_ref, hasher); +/// println!("Hash is {:x}!", hasher.finish()); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] // TODO: replace with ??? +pub fn hash(a: &T, into: &mut S) { + use hash::Hash; + NonNull::from(a).hash(into) +} + // Impls for function pointers macro_rules! fnptr_impls_safety_abi { ($FnTy: ty, $($Arg: ident),*) => { From 86d20f9342c8b6cfd24d199eacb26ed11a95da12 Mon Sep 17 00:00:00 2001 From: Dale Wijnand <344610+dwijnand@users.noreply.github.com> Date: Mon, 26 Nov 2018 19:23:20 +0000 Subject: [PATCH 0279/1984] FIXME is the new TODO --- src/libcore/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 6b4ee66bb02..7a57c365b23 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2526,7 +2526,7 @@ pub fn eq(a: *const T, b: *const T) -> bool { /// ptr::hash(five_ref, hasher); /// println!("Hash is {:x}!", hasher.finish()); /// ``` -#[stable(feature = "rust1", since = "1.0.0")] // TODO: replace with ??? +#[stable(feature = "rust1", since = "1.0.0")] // FIXME: replace with ??? pub fn hash(a: &T, into: &mut S) { use hash::Hash; NonNull::from(a).hash(into) From efb2949b93a8e650d8a4372bec87ee1f1f2e11b2 Mon Sep 17 00:00:00 2001 From: scalexm Date: Mon, 26 Nov 2018 20:37:43 +0100 Subject: [PATCH 0280/1984] Put all existential ty vars in the `ROOT` universe --- src/librustc/infer/canonical/canonicalizer.rs | 18 ++++++++++++------ .../nll/user-annotations/dump-fn-method.stderr | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index ddb520775da..406a36e61fb 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -346,12 +346,18 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> // `TyVar(vid)` is unresolved, track its universe index in the canonicalized // result - Err(ui) => self.canonicalize_ty_var( - CanonicalVarInfo { - kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) - }, - t - ) + Err(mut ui) => { + if !self.infcx.unwrap().tcx.sess.opts.debugging_opts.chalk { + // FIXME: perf problem described in #55921. + ui = ty::UniverseIndex::ROOT; + } + self.canonicalize_ty_var( + CanonicalVarInfo { + kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) + }, + t + ) + } } } diff --git a/src/test/ui/nll/user-annotations/dump-fn-method.stderr b/src/test/ui/nll/user-annotations/dump-fn-method.stderr index c963625c961..7683c20b5b6 100644 --- a/src/test/ui/nll/user-annotations/dump-fn-method.stderr +++ b/src/test/ui/nll/user-annotations/dump-fn-method.stderr @@ -16,7 +16,7 @@ error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubs LL | let x = >::method::; //~ ERROR [u8, u16, u32] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: user substs: Canonical { max_universe: U1, variables: [CanonicalVarInfo { kind: Ty(General(U1)) }, CanonicalVarInfo { kind: Ty(General(U1)) }], value: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } } +error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }, CanonicalVarInfo { kind: Ty(General(U0)) }], value: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } } --> $DIR/dump-fn-method.rs:54:5 | LL | y.method::(44, 66); //~ ERROR [^0, ^1, u32] From cd20be50912170842689e4f936c31c5a28184432 Mon Sep 17 00:00:00 2001 From: Jason Langenauer Date: Mon, 26 Nov 2018 21:21:17 +0100 Subject: [PATCH 0281/1984] Update outdated code comments in StringReader --- src/libsyntax/parse/lexer/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 0584cd5a3df..c90c62c13f9 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -60,11 +60,11 @@ pub struct StringReader<'a> { // cache a direct reference to the source text, so that we don't have to // retrieve it via `self.source_file.src.as_ref().unwrap()` all the time. src: Lrc, - /// Stack of open delimiters and their spans. Used for error message. token: token::Token, span: Span, /// The raw source span which *does not* take `override_span` into account span_src_raw: Span, + /// Stack of open delimiters and their spans. Used for error message. open_braces: Vec<(token::DelimToken, Span)>, /// The type and spans for all braces /// @@ -506,8 +506,7 @@ impl<'a> StringReader<'a> { } } - /// Advance the StringReader by one character. If a newline is - /// discovered, add it to the SourceFile's list of line start offsets. + /// Advance the StringReader by one character. crate fn bump(&mut self) { let next_src_index = self.src_index(self.next_pos); if next_src_index < self.end_src_index { From a1865edb75288b88cba7f26f754daee0b4a37f3f Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Wed, 21 Nov 2018 18:57:14 -0600 Subject: [PATCH 0282/1984] Add rustc-guide as a submodule --- .gitmodules | 3 +++ src/doc/rustc-guide | 1 + 2 files changed, 4 insertions(+) create mode 160000 src/doc/rustc-guide diff --git a/.gitmodules b/.gitmodules index bf9bdd9a5b4..5cc4cab62d1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -62,3 +62,6 @@ url = https://github.com/rust-lang-nursery/clang.git branch = rust-release-80-v1 +[submodule "src/doc/rustc-guide"] + path = src/doc/rustc-guide + url = https://github.com/rust-lang/rustc-guide.git diff --git a/src/doc/rustc-guide b/src/doc/rustc-guide new file mode 160000 index 00000000000..3a804956e3c --- /dev/null +++ b/src/doc/rustc-guide @@ -0,0 +1 @@ +Subproject commit 3a804956e3c28d7e44e38804207a00013594e1d3 From 6494f1e60e1931ac62eaef0a203bcb013fd77acf Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Mon, 26 Nov 2018 15:03:13 -0600 Subject: [PATCH 0283/1984] rustc-guide has moved --- CONTRIBUTING.md | 4 ++-- README.md | 2 +- src/README.md | 2 +- src/doc/rustc/src/contributing.md | 4 ++-- src/librustc/README.md | 2 +- src/librustc/dep_graph/README.md | 2 +- src/librustc/dep_graph/graph.rs | 2 +- src/librustc/hir/mod.rs | 2 +- src/librustc/infer/canonical/canonicalizer.rs | 6 +++--- src/librustc/infer/canonical/mod.rs | 2 +- src/librustc/infer/canonical/query_response.rs | 4 ++-- src/librustc/infer/canonical/substitute.rs | 2 +- src/librustc/infer/higher_ranked/mod.rs | 2 +- src/librustc/infer/lexical_region_resolve/README.md | 2 +- src/librustc/infer/region_constraints/README.md | 4 ++-- src/librustc/lib.rs | 2 +- src/librustc/middle/region.rs | 2 +- src/librustc/mir/mod.rs | 2 +- src/librustc/traits/coherence.rs | 4 ++-- src/librustc/traits/mod.rs | 2 +- src/librustc/traits/query/type_op/mod.rs | 2 +- src/librustc/traits/select.rs | 6 +++--- src/librustc/traits/specialize/mod.rs | 2 +- src/librustc/ty/context.rs | 2 +- src/librustc/ty/sty.rs | 2 +- src/librustc_borrowck/borrowck/README.md | 2 +- src/librustc_codegen_llvm/README.md | 2 +- src/librustc_driver/README.md | 2 +- src/librustc_target/README.md | 2 +- src/librustc_typeck/README.md | 4 ++-- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/variance/mod.rs | 2 +- src/librustc_typeck/variance/terms.rs | 4 ++-- src/librustdoc/README.md | 2 +- src/libsyntax/README.md | 4 ++-- src/test/COMPILER_TESTS.md | 2 +- 36 files changed, 48 insertions(+), 48 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e04b1bdfefd..137fe613207 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -640,7 +640,7 @@ are: * **Google!** ([search only in Rust Documentation][gsearchdocs] to find types, traits, etc. quickly) * Don't be afraid to ask! The Rust community is friendly and helpful. -[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/about-this-guide.html +[rustc guide]: https://rust-lang.github.io/rustc-guide/about-this-guide.html [gdfrustc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ [gsearchdocs]: https://www.google.com/search?q=site:doc.rust-lang.org+your+query+here [rif]: http://internals.rust-lang.org @@ -648,5 +648,5 @@ are: [rustforge]: https://forge.rust-lang.org/ [tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/ [ro]: http://www.rustaceans.org/ -[rctd]: https://rust-lang-nursery.github.io/rustc-guide/tests/intro.html +[rctd]: https://rust-lang.github.io/rustc-guide/tests/intro.html [cheatsheet]: https://buildbot2.rust-lang.org/homu/ diff --git a/README.md b/README.md index 0e5b7170bc6..37442661bcb 100644 --- a/README.md +++ b/README.md @@ -233,7 +233,7 @@ Also, you may find the [rustdocs for the compiler itself][rustdocs] useful. [IRC]: https://en.wikipedia.org/wiki/Internet_Relay_Chat [#rust]: irc://irc.mozilla.org/rust [#rust-beginners]: irc://irc.mozilla.org/rust-beginners -[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/about-this-guide.html +[rustc guide]: https://rust-lang.github.io/rustc-guide/about-this-guide.html [rustdocs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ ## License diff --git a/src/README.md b/src/README.md index a4f89960a0b..65228915866 100644 --- a/src/README.md +++ b/src/README.md @@ -12,4 +12,4 @@ There is also useful content in the following READMEs, which are gradually being - https://github.com/rust-lang/rust/tree/master/src/librustc/infer/higher_ranked - https://github.com/rust-lang/rust/tree/master/src/librustc/infer/lexical_region_resolve -[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/about-this-guide.html +[rustc guide]: https://rust-lang.github.io/rustc-guide/about-this-guide.html diff --git a/src/doc/rustc/src/contributing.md b/src/doc/rustc/src/contributing.md index fcb8e6b27db..3a1cafe8a61 100644 --- a/src/doc/rustc/src/contributing.md +++ b/src/doc/rustc/src/contributing.md @@ -1,6 +1,6 @@ # Contributing to rustc We'd love to have your help improving `rustc`! To that end, we've written [a -whole book](https://rust-lang-nursery.github.io/rustc-guide/) on its +whole book](https://rust-lang.github.io/rustc-guide/) on its internals, how it works, and how to get started working on it. To learn -more, you'll want to check that out. \ No newline at end of file +more, you'll want to check that out. diff --git a/src/librustc/README.md b/src/librustc/README.md index 9909ff91a18..c0e5c542bdc 100644 --- a/src/librustc/README.md +++ b/src/librustc/README.md @@ -1,3 +1,3 @@ For more information about how rustc works, see the [rustc guide]. -[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/ +[rustc guide]: https://rust-lang.github.io/rustc-guide/ diff --git a/src/librustc/dep_graph/README.md b/src/librustc/dep_graph/README.md index f1f383d7ad1..91a06e452e5 100644 --- a/src/librustc/dep_graph/README.md +++ b/src/librustc/dep_graph/README.md @@ -1,4 +1,4 @@ To learn more about how dependency tracking works in rustc, see the [rustc guide]. -[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/query.html +[rustc guide]: https://rust-lang.github.io/rustc-guide/query.html diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 63b749c548e..4c94c993ab4 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -195,7 +195,7 @@ impl DepGraph { /// - If you need 3+ arguments, use a tuple for the /// `arg` parameter. /// - /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/incremental-compilation.html + /// [rustc guide]: https://rust-lang.github.io/rustc-guide/incremental-compilation.html pub fn with_task<'gcx, C, A, R>(&self, key: DepNode, cx: C, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index e28193be34a..1674320165e 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -689,7 +689,7 @@ pub struct WhereEqPredicate { /// /// For more details, see the [rustc guide]. /// -/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/hir.html +/// [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Crate { pub module: Mod, diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index ddb520775da..08cd3395ba1 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -13,7 +13,7 @@ //! For an overview of what canonicalization is and how it fits into //! rustc, check out the [chapter in the rustc guide][c]. //! -//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html +//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html use infer::canonical::{ Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, Canonicalized, @@ -44,7 +44,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { /// To get a good understanding of what is happening here, check /// out the [chapter in the rustc guide][c]. /// - /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query + /// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query pub fn canonicalize_query( &self, value: &V, @@ -92,7 +92,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { /// To get a good understanding of what is happening here, check /// out the [chapter in the rustc guide][c]. /// - /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query-result + /// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query-result pub fn canonicalize_response(&self, value: &V) -> Canonicalized<'gcx, V> where V: TypeFoldable<'tcx> + Lift<'gcx>, diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index 230f8958b33..6b0fa79b201 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -29,7 +29,7 @@ //! For a more detailed look at what is happening here, check //! out the [chapter in the rustc guide][c]. //! -//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html +//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html use infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin}; use rustc_data_structures::indexed_vec::IndexVec; diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index d32594ebdf3..8d2b1d74c55 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -15,7 +15,7 @@ //! For an overview of what canonicaliation is and how it fits into //! rustc, check out the [chapter in the rustc guide][c]. //! -//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html +//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html use infer::canonical::substitute::substitute_value; use infer::canonical::{ @@ -184,7 +184,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { /// To get a good understanding of what is happening here, check /// out the [chapter in the rustc guide][c]. /// - /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#processing-the-canonicalized-query-result + /// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html#processing-the-canonicalized-query-result pub fn instantiate_query_response_and_region_obligations( &self, cause: &ObligationCause<'tcx>, diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs index e2110e148de..ab575882f8a 100644 --- a/src/librustc/infer/canonical/substitute.rs +++ b/src/librustc/infer/canonical/substitute.rs @@ -14,7 +14,7 @@ //! For an overview of what canonicalization is and how it fits into //! rustc, check out the [chapter in the rustc guide][c]. //! -//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html +//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html use infer::canonical::{Canonical, CanonicalVarValues}; use ty::fold::TypeFoldable; diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index 16140e748aa..cf91b858076 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -329,7 +329,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// For more information about how placeholders and HRTBs work, see /// the [rustc guide]. /// - /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html + /// [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/hrtb.html pub fn replace_bound_vars_with_placeholders( &self, binder: &ty::Binder diff --git a/src/librustc/infer/lexical_region_resolve/README.md b/src/librustc/infer/lexical_region_resolve/README.md index 6e1c4191173..4483e522f3a 100644 --- a/src/librustc/infer/lexical_region_resolve/README.md +++ b/src/librustc/infer/lexical_region_resolve/README.md @@ -3,7 +3,7 @@ > WARNING: This README is obsolete and will be removed soon! For > more info on how the current borrowck works, see the [rustc guide]. -[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html +[rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html ## Terminology diff --git a/src/librustc/infer/region_constraints/README.md b/src/librustc/infer/region_constraints/README.md index 61603e6dee6..775bbf955b8 100644 --- a/src/librustc/infer/region_constraints/README.md +++ b/src/librustc/infer/region_constraints/README.md @@ -3,7 +3,7 @@ > WARNING: This README is obsolete and will be removed soon! For > more info on how the current borrowck works, see the [rustc guide]. -[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html +[rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html ## Terminology @@ -18,7 +18,7 @@ constraints over the course of a function. Finally, at the end of processing a function, we process and solve the constraints all at once. -[ti]: https://rust-lang-nursery.github.io/rustc-guide/type-inference.html +[ti]: https://rust-lang.github.io/rustc-guide/type-inference.html The constraints are always of one of three possible forms: diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 0aa964a44fd..edc97238f05 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -30,7 +30,7 @@ //! //! For more information about how rustc works, see the [rustc guide]. //! -//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/ +//! [rustc guide]: https://rust-lang.github.io/rustc-guide/ //! //! # Note //! diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index d00fbdeca21..35d1a4dd2cb 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -14,7 +14,7 @@ //! For more information about how MIR-based region-checking works, //! see the [rustc guide]. //! -//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html +//! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html use ich::{StableHashingContext, NodeIdHashingMode}; use util::nodemap::{FxHashMap, FxHashSet}; diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index af1255c438a..368f83eb611 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -10,7 +10,7 @@ //! MIR datatypes and passes. See the [rustc guide] for more info. //! -//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/index.html +//! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/index.html use hir::def::CtorKind; use hir::def_id::DefId; diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index b7a84c99308..4bf8ba0d6d1 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -11,8 +11,8 @@ //! See rustc guide chapters on [trait-resolution] and [trait-specialization] for more info on how //! this works. //! -//! [trait-resolution]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html -//! [trait-specialization]: https://rust-lang-nursery.github.io/rustc-guide/traits/specialization.html +//! [trait-resolution]: https://rust-lang.github.io/rustc-guide/traits/resolution.html +//! [trait-specialization]: https://rust-lang.github.io/rustc-guide/traits/specialization.html use hir::def_id::{DefId, LOCAL_CRATE}; use syntax_pos::DUMMY_SP; diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 8c3cd5e6612..e582a902046 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -10,7 +10,7 @@ //! Trait Resolution. See [rustc guide] for more info on how this works. //! -//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html +//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html pub use self::SelectionError::*; pub use self::FulfillmentErrorCode::*; diff --git a/src/librustc/traits/query/type_op/mod.rs b/src/librustc/traits/query/type_op/mod.rs index d20d43cf757..f8f9650ebe1 100644 --- a/src/librustc/traits/query/type_op/mod.rs +++ b/src/librustc/traits/query/type_op/mod.rs @@ -53,7 +53,7 @@ pub trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug { /// first canonicalize the key and then invoke the query on the tcx, /// which produces the resulting query region constraints. /// -/// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html +/// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + Lift<'gcx> { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 0f59f478cb4..fb4c9f3bad7 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -10,7 +10,7 @@ //! See [rustc guide] for more info on how this works. //! -//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#selection +//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html#selection use self::EvaluationResult::*; use self::SelectionCandidate::*; @@ -1173,7 +1173,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // candidates. See [rustc guide] for more details. // // [rustc guide]: - // https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#candidate-assembly + // https://rust-lang.github.io/rustc-guide/traits/resolution.html#candidate-assembly fn candidate_from_obligation<'o>( &mut self, @@ -2720,7 +2720,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // type error. See [rustc guide] for more details. // // [rustc guide]: - // https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#confirmation + // https://rust-lang.github.io/rustc-guide/traits/resolution.html#confirmation fn confirm_candidate( &mut self, diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index d3dc1655b0d..19ef3171b13 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -17,7 +17,7 @@ //! See the [rustc guide] for a bit more detail on how specialization //! fits together with the rest of the trait machinery. //! -//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/specialization.html +//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/specialization.html use super::{SelectionContext, FulfillmentContext}; use super::util::impl_trait_ref_and_oblig; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 22d5ea6e4bc..9f26499e770 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -876,7 +876,7 @@ pub struct FreeRegionInfo { /// various **compiler queries** that have been performed. See the /// [rustc guide] for more details. /// -/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/ty.html +/// [rustc guide]: https://rust-lang.github.io/rustc-guide/ty.html #[derive(Copy, Clone)] pub struct TyCtxt<'a, 'gcx: 'tcx, 'tcx: 'a> { gcx: &'a GlobalCtxt<'gcx>, diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 3056abba956..a18e3a27546 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1138,7 +1138,7 @@ pub type Region<'tcx> = &'tcx RegionKind; /// /// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/ /// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/ -/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html +/// [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/hrtb.html #[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)] pub enum RegionKind { // Region bound in a type or fn declaration which will be diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index 8bc0b4969b8..a05c56e3629 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -3,7 +3,7 @@ > WARNING: This README is more or less obsolete, and will be removed > soon! The new system is described in the [rustc guide]. -[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html +[rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html This pass has the job of enforcing memory safety. This is a subtle topic. This docs aim to explain both the practice and the theory diff --git a/src/librustc_codegen_llvm/README.md b/src/librustc_codegen_llvm/README.md index 8d1c9a52b24..dda2e5ac18f 100644 --- a/src/librustc_codegen_llvm/README.md +++ b/src/librustc_codegen_llvm/README.md @@ -4,4 +4,4 @@ that runs towards the end of the compilation process. For more information about how codegen works, see the [rustc guide]. -[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/codegen.html +[rustc guide]: https://rust-lang.github.io/rustc-guide/codegen.html diff --git a/src/librustc_driver/README.md b/src/librustc_driver/README.md index fef249a9e4e..c4d73953e9b 100644 --- a/src/librustc_driver/README.md +++ b/src/librustc_driver/README.md @@ -7,4 +7,4 @@ options). For more information about how the driver works, see the [rustc guide]. -[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/rustc-driver.html +[rustc guide]: https://rust-lang.github.io/rustc-guide/rustc-driver.html diff --git a/src/librustc_target/README.md b/src/librustc_target/README.md index f5b1acb1921..a22000ea9d2 100644 --- a/src/librustc_target/README.md +++ b/src/librustc_target/README.md @@ -3,4 +3,4 @@ specific to different compilation targets and so forth. For more information about how rustc works, see the [rustc guide]. -[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/ +[rustc guide]: https://rust-lang.github.io/rustc-guide/ diff --git a/src/librustc_typeck/README.md b/src/librustc_typeck/README.md index f00597cb27f..fdcbd935524 100644 --- a/src/librustc_typeck/README.md +++ b/src/librustc_typeck/README.md @@ -1,5 +1,5 @@ For high-level intro to how type checking works in rustc, see the [type checking] chapter of the [rustc guide]. -[type checking]: https://rust-lang-nursery.github.io/rustc-guide/type-checking.html -[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/ +[type checking]: https://rust-lang.github.io/rustc-guide/type-checking.html +[rustc guide]: https://rust-lang.github.io/rustc-guide/ diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index ac338ba6678..37f4ae56779 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -10,7 +10,7 @@ //! Method lookup: the secret sauce of Rust. See the [rustc guide] chapter. //! -//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/method-lookup.html +//! [rustc guide]: https://rust-lang.github.io/rustc-guide/method-lookup.html use check::FnCtxt; use hir::def::Def; diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index 7cc56bc192b..e3c82d50a8d 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -11,7 +11,7 @@ //! Module for inferring the variance of type and lifetime parameters. See the [rustc guide] //! chapter for more info. //! -//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/variance.html +//! [rustc guide]: https://rust-lang.github.io/rustc-guide/variance.html use arena; use rustc::hir; diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index 087d53b92d4..3692221a3fc 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -89,8 +89,8 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx> // See the following for a discussion on dep-graph management. // - // - https://rust-lang-nursery.github.io/rustc-guide/query.html - // - https://rust-lang-nursery.github.io/rustc-guide/variance.html + // - https://rust-lang.github.io/rustc-guide/query.html + // - https://rust-lang.github.io/rustc-guide/variance.html tcx.hir.krate().visit_all_item_likes(&mut terms_cx); terms_cx diff --git a/src/librustdoc/README.md b/src/librustdoc/README.md index 2cfe43a8389..e4f7bc30e3f 100644 --- a/src/librustdoc/README.md +++ b/src/librustdoc/README.md @@ -1,3 +1,3 @@ For more information about how `librustdoc` works, see the [rustc guide]. -[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/rustdoc.html +[rustc guide]: https://rust-lang.github.io/rustc-guide/rustdoc.html diff --git a/src/libsyntax/README.md b/src/libsyntax/README.md index 7214203830e..daa252ef455 100644 --- a/src/libsyntax/README.md +++ b/src/libsyntax/README.md @@ -5,5 +5,5 @@ lexer, macro expander, and utilities for traversing ASTs. For more information about how these things work in rustc, see the rustc guide: -- [Parsing](https://rust-lang-nursery.github.io/rustc-guide/the-parser.html) -- [Macro Expansion](https://rust-lang-nursery.github.io/rustc-guide/macro-expansion.html) +- [Parsing](https://rust-lang.github.io/rustc-guide/the-parser.html) +- [Macro Expansion](https://rust-lang.github.io/rustc-guide/macro-expansion.html) diff --git a/src/test/COMPILER_TESTS.md b/src/test/COMPILER_TESTS.md index 81a46ea0fe7..c4ca4781343 100644 --- a/src/test/COMPILER_TESTS.md +++ b/src/test/COMPILER_TESTS.md @@ -1,4 +1,4 @@ # Compiler Test Documentation Documentation the compiler testing framework has moved to -[the rustc guide](https://rust-lang-nursery.github.io/rustc-guide/tests/intro.html). +[the rustc guide](https://rust-lang.github.io/rustc-guide/tests/intro.html). From fba116fc5fb7018faeb1834d42422d7bdbcc4f64 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 23 Nov 2018 00:50:15 +0300 Subject: [PATCH 0284/1984] Remove duplicate tests for uniform paths --- .../ambiguity-macros-nested.rs | 29 -------------- .../ambiguity-macros-nested.stderr | 23 ----------- .../ambiguity-macros.rs | 27 ------------- .../ambiguity-macros.stderr | 23 ----------- .../ambiguity-nested.rs | 24 ------------ .../ambiguity-nested.stderr | 20 ---------- .../uniform-paths-forward-compat/ambiguity.rs | 20 ---------- .../ambiguity.stderr | 20 ---------- .../block-scoped-shadow.rs | 21 ---------- .../block-scoped-shadow.stderr | 39 ------------------- .../issue-54253.rs | 27 ------------- .../issue-54253.stderr | 9 ----- .../uniform-paths-forward-compat/redundant.rs | 30 -------------- 13 files changed, 312 deletions(-) delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.rs delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.stderr delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.rs delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.stderr delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.rs delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.stderr delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.rs delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.stderr delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.rs delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.stderr delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/redundant.rs diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.rs deleted file mode 100644 index 4819711115c..00000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2018 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. - -// edition:2018 - -// This test is similar to `ambiguity-macros.rs`, but nested in a module. - -mod foo { - pub use std::io; - //~^ ERROR `std` is ambiguous - - macro_rules! m { - () => { - mod std { - pub struct io; - } - } - } - m!(); -} - -fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.stderr deleted file mode 100644 index 204e0a7e141..00000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) - --> $DIR/ambiguity-macros-nested.rs:16:13 - | -LL | pub use std::io; - | ^^^ ambiguous name - | - = note: `std` could refer to a built-in extern crate - = help: use `::std` to refer to this extern crate unambiguously -note: `std` could also refer to the module defined here - --> $DIR/ambiguity-macros-nested.rs:21:13 - | -LL | / mod std { -LL | | pub struct io; -LL | | } - | |_____________^ -... -LL | m!(); - | ----- in this macro invocation - = help: use `self::std` to refer to this module unambiguously - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.rs deleted file mode 100644 index 148320de556..00000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2018 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. - -// edition:2018 - -// This test is similar to `ambiguity.rs`, but with macros defining local items. - -use std::io; -//~^ ERROR `std` is ambiguous - -macro_rules! m { - () => { - mod std { - pub struct io; - } - } -} -m!(); - -fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.stderr deleted file mode 100644 index ac8d3b9d0cb..00000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) - --> $DIR/ambiguity-macros.rs:15:5 - | -LL | use std::io; - | ^^^ ambiguous name - | - = note: `std` could refer to a built-in extern crate - = help: use `::std` to refer to this extern crate unambiguously -note: `std` could also refer to the module defined here - --> $DIR/ambiguity-macros.rs:20:9 - | -LL | / mod std { -LL | | pub struct io; -LL | | } - | |_________^ -... -LL | m!(); - | ----- in this macro invocation - = help: use `self::std` to refer to this module unambiguously - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.rs deleted file mode 100644 index 2791d4580da..00000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2018 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. - -// edition:2018 - -// This test is similar to `ambiguity.rs`, but nested in a module. - -mod foo { - pub use std::io; - //~^ ERROR `std` is ambiguous - - mod std { - pub struct io; - } -} - -fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.stderr deleted file mode 100644 index 7bcfc563d39..00000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) - --> $DIR/ambiguity-nested.rs:16:13 - | -LL | pub use std::io; - | ^^^ ambiguous name - | - = note: `std` could refer to a built-in extern crate - = help: use `::std` to refer to this extern crate unambiguously -note: `std` could also refer to the module defined here - --> $DIR/ambiguity-nested.rs:19:5 - | -LL | / mod std { -LL | | pub struct io; -LL | | } - | |_____^ - = help: use `self::std` to refer to this module unambiguously - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.rs deleted file mode 100644 index 2bfbb6b2871..00000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2018 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. - -// edition:2018 - -use std::io; -//~^ ERROR `std` is ambiguous - -mod std { - pub struct io; -} - -fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.stderr deleted file mode 100644 index beeb74654e5..00000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) - --> $DIR/ambiguity.rs:13:5 - | -LL | use std::io; - | ^^^ ambiguous name - | - = note: `std` could refer to a built-in extern crate - = help: use `::std` to refer to this extern crate unambiguously -note: `std` could also refer to the module defined here - --> $DIR/ambiguity.rs:16:1 - | -LL | / mod std { -LL | | pub struct io; -LL | | } - | |_^ - = help: use `self::std` to refer to this module unambiguously - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.rs deleted file mode 100644 index 2853b4b3a5b..00000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2018 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. - -// edition:2018 - -struct std; - -fn main() { - fn std() {} - enum std {} - use std as foo; - //~^ ERROR `std` is ambiguous - //~| ERROR `std` is ambiguous -} diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.stderr deleted file mode 100644 index 5d539e2d59f..00000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) - --> $DIR/block-scoped-shadow.rs:18:9 - | -LL | use std as foo; - | ^^^ ambiguous name - | -note: `std` could refer to the enum defined here - --> $DIR/block-scoped-shadow.rs:17:5 - | -LL | enum std {} - | ^^^^^^^^^^^ -note: `std` could also refer to the struct defined here - --> $DIR/block-scoped-shadow.rs:13:1 - | -LL | struct std; - | ^^^^^^^^^^^ - = help: use `self::std` to refer to this struct unambiguously - -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) - --> $DIR/block-scoped-shadow.rs:18:9 - | -LL | use std as foo; - | ^^^ ambiguous name - | -note: `std` could refer to the function defined here - --> $DIR/block-scoped-shadow.rs:16:5 - | -LL | fn std() {} - | ^^^^^^^^^^^ -note: `std` could also refer to the unit struct defined here - --> $DIR/block-scoped-shadow.rs:13:1 - | -LL | struct std; - | ^^^^^^^^^^^ - = help: use `self::std` to refer to this unit struct unambiguously - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs deleted file mode 100644 index ef2a1e3c70c..00000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2018 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. - -// edition:2018 - -// Dummy import that previously introduced uniform path canaries. -use std; - -// fn version() -> &'static str {""} - -mod foo { - // Error wasn't reported, despite `version` being commented out above. - use crate::version; //~ ERROR unresolved import `crate::version` - - fn bar() { - version(); - } -} - -fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr deleted file mode 100644 index 6dcc451c60a..00000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0432]: unresolved import `crate::version` - --> $DIR/issue-54253.rs:20:9 - | -LL | use crate::version; //~ ERROR unresolved import `crate::version` - | ^^^^^^^^^^^^^^ no `version` in the root - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/redundant.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/redundant.rs deleted file mode 100644 index 05048cfd451..00000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/redundant.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2018 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. - -// run-pass -// edition:2018 - -use std; -use std::io; - -mod foo { - pub use std as my_std; -} - -mod bar { - pub use std::{self}; -} - -fn main() { - io::stdout(); - self::std::io::stdout(); - foo::my_std::io::stdout(); - bar::std::io::stdout(); -} From 5558c07c6e24b6677e3a60a1314d705c8c23ab47 Mon Sep 17 00:00:00 2001 From: Dale Wijnand <344610+dwijnand@users.noreply.github.com> Date: Mon, 26 Nov 2018 21:31:12 +0000 Subject: [PATCH 0285/1984] Fix ptr::hex doc example --- src/libcore/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 7a57c365b23..c0e8e581144 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2523,7 +2523,7 @@ pub fn eq(a: *const T, b: *const T) -> bool { /// let five_ref = &five; /// /// let mut hasher = DefaultHasher::new(); -/// ptr::hash(five_ref, hasher); +/// ptr::hash(five_ref, &mut hasher); /// println!("Hash is {:x}!", hasher.finish()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] // FIXME: replace with ??? From dae4c7b1ff62da4901caf28653baa3133a40496c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 18 Nov 2018 03:25:59 +0300 Subject: [PATCH 0286/1984] resolve: Implement edition hygiene for imports and absolute paths Use per-span hygiene in a few other places in resolve Prefer `rust_2015`/`rust_2018` helpers to comparing editions --- src/librustc/ty/context.rs | 11 +-- src/librustc/ty/item_path.rs | 3 +- src/librustc_resolve/build_reduced_graph.rs | 19 +++--- src/librustc_resolve/error_reporting.rs | 5 +- src/librustc_resolve/lib.rs | 67 +++++++++---------- src/librustc_resolve/macros.rs | 5 +- src/libsyntax/parse/parser.rs | 29 ++++---- src/libsyntax_pos/lib.rs | 10 +++ src/libsyntax_pos/symbol.rs | 3 +- .../auxiliary/edition-imports-2015.rs | 19 ++++++ .../proc-macro/edition-imports-2018.rs | 24 +++++++ src/test/ui/editions/auxiliary/absolute.rs | 1 + .../auxiliary/edition-imports-2015.rs | 17 +++++ .../auxiliary/edition-imports-2018.rs | 17 +++++ src/test/ui/editions/edition-imports-2015.rs | 28 ++++++++ .../ui/editions/edition-imports-2015.stderr | 10 +++ src/test/ui/editions/edition-imports-2018.rs | 33 +++++++++ 17 files changed, 226 insertions(+), 75 deletions(-) create mode 100644 src/test/ui-fulldeps/proc-macro/auxiliary/edition-imports-2015.rs create mode 100644 src/test/ui-fulldeps/proc-macro/edition-imports-2018.rs create mode 100644 src/test/ui/editions/auxiliary/absolute.rs create mode 100644 src/test/ui/editions/auxiliary/edition-imports-2015.rs create mode 100644 src/test/ui/editions/auxiliary/edition-imports-2018.rs create mode 100644 src/test/ui/editions/edition-imports-2015.rs create mode 100644 src/test/ui/editions/edition-imports-2015.stderr create mode 100644 src/test/ui/editions/edition-imports-2018.rs diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 22d5ea6e4bc..d383d8375a9 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1478,15 +1478,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// done with either: `-Ztwo-phase-borrows`, `#![feature(nll)]`, /// or by opting into an edition after 2015. pub fn two_phase_borrows(self) -> bool { - if self.features().nll || self.sess.opts.debugging_opts.two_phase_borrows { - return true; - } - - match self.sess.edition() { - Edition::Edition2015 => false, - Edition::Edition2018 => true, - _ => true, - } + self.sess.rust_2018() || self.features().nll || + self.sess.opts.debugging_opts.two_phase_borrows } /// What mode(s) of borrowck should we run? AST? MIR? both? diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index f6c90ab0a1a..350e55288ea 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -14,7 +14,6 @@ use ty::{self, DefIdTree, Ty, TyCtxt}; use middle::cstore::{ExternCrate, ExternCrateSource}; use syntax::ast; use syntax::symbol::{keywords, LocalInternedString, Symbol}; -use syntax_pos::edition::Edition; use std::cell::Cell; use std::fmt::Debug; @@ -140,7 +139,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { debug!("push_krate_path: name={:?}", name); buffer.push(&name); } - } else if self.sess.edition() == Edition::Edition2018 && !pushed_prelude_crate { + } else if self.sess.rust_2018() && !pushed_prelude_crate { SHOULD_PREFIX_WITH_CRATE.with(|flag| { // We only add the `crate::` keyword where appropriate. In particular, // when we've not previously pushed a prelude crate to this path. diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 72fe7355e4c..3f0780191fb 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -133,14 +133,17 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // The root is prepended lazily, when the first non-empty prefix or terminating glob // appears, so imports in braced groups can have roots prepended independently. let is_glob = if let ast::UseTreeKind::Glob = use_tree.kind { true } else { false }; - let crate_root = if !self.session.rust_2018() && - prefix_iter.peek().map_or(is_glob, |seg| !seg.ident.is_path_segment_keyword()) { - Some(Segment::from_ident(Ident::new( - keywords::CrateRoot.name(), use_tree.prefix.span.shrink_to_lo() - ))) - } else { - None - }; + let crate_root = match prefix_iter.peek() { + Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => { + Some(seg.ident.span.ctxt()) + } + None if is_glob && use_tree.span.rust_2015() => { + Some(use_tree.span.ctxt()) + } + _ => None, + }.map(|ctxt| Segment::from_ident(Ident::new( + keywords::CrateRoot.name(), use_tree.prefix.span.shrink_to_lo().with_ctxt(ctxt) + ))); let prefix = crate_root.into_iter().chain(prefix_iter).collect::>(); debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix); diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index 263d23d133e..e2a6303f579 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -33,7 +33,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { (Some(fst), Some(snd)) if fst.ident.name == keywords::CrateRoot.name() && !snd.ident.is_path_segment_keyword() => {} // `ident::...` on 2018 - (Some(fst), _) if self.session.rust_2018() && !fst.ident.is_path_segment_keyword() => { + (Some(fst), _) if fst.ident.span.rust_2018() && + !fst.ident.is_path_segment_keyword() => { // Insert a placeholder that's later replaced by `self`/`super`/etc. path.insert(0, Segment::from_ident(keywords::Invalid.ident())); } @@ -141,7 +142,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { mut path: Vec, parent_scope: &ParentScope<'b>, ) -> Option<(Vec, Option)> { - if !self.session.rust_2018() { + if path[1].ident.span.rust_2015() { return None; } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 443b1ccdef8..2e7ed80c91b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2354,14 +2354,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } fn future_proof_import(&mut self, use_tree: &ast::UseTree) { - if !self.session.rust_2018() { - return; - } - let segments = &use_tree.prefix.segments; if !segments.is_empty() { let ident = segments[0].ident; - if ident.is_path_segment_keyword() { + if ident.is_path_segment_keyword() || ident.span.rust_2015() { return; } @@ -3181,10 +3177,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // Try to lookup the name in more relaxed fashion for better error reporting. let ident = path.last().unwrap().ident; - let candidates = this.lookup_import_candidates(ident.name, ns, is_expected); + let candidates = this.lookup_import_candidates(ident, ns, is_expected); if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) { let enum_candidates = - this.lookup_import_candidates(ident.name, ns, is_enum_variant); + this.lookup_import_candidates(ident, ns, is_enum_variant); let mut enum_candidates = enum_candidates.iter() .map(|suggestion| import_candidate_to_paths(&suggestion)).collect::>(); enum_candidates.sort(); @@ -3772,7 +3768,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { continue; } if name == keywords::Extern.name() || - name == keywords::CrateRoot.name() && self.session.rust_2018() { + name == keywords::CrateRoot.name() && ident.span.rust_2018() { module = Some(ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude)); continue; @@ -3875,7 +3871,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let msg = if module_def == self.graph_root.def() { let is_mod = |def| match def { Def::Mod(..) => true, _ => false }; let mut candidates = - self.lookup_import_candidates(name, TypeNS, is_mod); + self.lookup_import_candidates(ident, TypeNS, is_mod); candidates.sort_by_cached_key(|c| { (c.path.segments.len(), c.path.to_string()) }); @@ -3911,11 +3907,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { path_span: Span, second_binding: Option<&NameBinding>, ) { - // In the 2018 edition this lint is a hard error, so nothing to do - if self.session.rust_2018() { - return - } - let (diag_id, diag_span) = match crate_lint { CrateLint::No => return, CrateLint::SimplePath(id) => (id, path_span), @@ -3924,8 +3915,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { }; let first_name = match path.get(0) { - Some(ident) => ident.ident.name, - None => return, + // In the 2018 edition this lint is a hard error, so nothing to do + Some(seg) if seg.ident.span.rust_2015() => seg.ident.name, + _ => return, }; // We're only interested in `use` paths which should start with @@ -4507,7 +4499,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } fn lookup_import_candidates_from_module(&mut self, - lookup_name: Name, + lookup_ident: Ident, namespace: Namespace, start_module: &'a ModuleData<'a>, crate_name: Ident, @@ -4534,11 +4526,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { if !name_binding.is_importable() { return; } // collect results based on the filter function - if ident.name == lookup_name && ns == namespace { + if ident.name == lookup_ident.name && ns == namespace { if filter_fn(name_binding.def()) { // create the path let mut segms = path_segments.clone(); - if self.session.rust_2018() { + if lookup_ident.span.rust_2018() { // crate-local absolute paths start with `crate::` in edition 2018 // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660) segms.insert( @@ -4572,7 +4564,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let is_extern_crate_that_also_appears_in_prelude = name_binding.is_extern_crate() && - self.session.rust_2018(); + lookup_ident.span.rust_2018(); let is_visible_to_user = !in_module_is_extern || name_binding.vis == ty::Visibility::Public; @@ -4599,16 +4591,16 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { /// NOTE: The method does not look into imports, but this is not a problem, /// since we report the definitions (thus, the de-aliased imports). fn lookup_import_candidates(&mut self, - lookup_name: Name, + lookup_ident: Ident, namespace: Namespace, filter_fn: FilterFn) -> Vec where FilterFn: Fn(Def) -> bool { let mut suggestions = self.lookup_import_candidates_from_module( - lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn); + lookup_ident, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn); - if self.session.rust_2018() { + if lookup_ident.span.rust_2018() { let extern_prelude_names = self.extern_prelude.clone(); for (ident, _) in extern_prelude_names.into_iter() { if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name, @@ -4620,7 +4612,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.populate_module_if_necessary(&crate_root); suggestions.extend(self.lookup_import_candidates_from_module( - lookup_name, namespace, crate_root, ident, &filter_fn)); + lookup_ident, namespace, crate_root, ident, &filter_fn)); } } } @@ -4712,19 +4704,26 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { ast::VisibilityKind::Restricted { ref path, id, .. } => { // For visibilities we are not ready to provide correct implementation of "uniform // paths" right now, so on 2018 edition we only allow module-relative paths for now. - let first_ident = path.segments[0].ident; - if self.session.rust_2018() && !first_ident.is_path_segment_keyword() { + // On 2015 edition visibilities are resolved as crate-relative by default, + // so we are prepending a root segment if necessary. + let ident = path.segments.get(0).expect("empty path in visibility").ident; + let crate_root = if ident.is_path_segment_keyword() { + None + } else if ident.span.rust_2018() { let msg = "relative paths are not supported in visibilities on 2018 edition"; - self.session.struct_span_err(first_ident.span, msg) + self.session.struct_span_err(ident.span, msg) .span_suggestion(path.span, "try", format!("crate::{}", path)) .emit(); return ty::Visibility::Public; - } - // On 2015 visibilities are resolved as crate-relative by default, - // add starting root segment if necessary. - let segments = path.make_root().iter().chain(path.segments.iter()) - .map(|seg| Segment { ident: seg.ident, id: Some(seg.id) }) - .collect::>(); + } else { + let ctxt = ident.span.ctxt(); + Some(Segment::from_ident(Ident::new( + keywords::CrateRoot.name(), path.span.shrink_to_lo().with_ctxt(ctxt) + ))) + }; + + let segments = crate_root.into_iter() + .chain(path.segments.iter().map(|seg| seg.into())).collect::>(); let def = self.smart_resolve_path_fragment( id, None, @@ -4837,7 +4836,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { help_msgs.push(format!("consider adding an explicit import of \ `{ident}` to disambiguate", ident = ident)) } - if b.is_extern_crate() && self.session.rust_2018() { + if b.is_extern_crate() && ident.span.rust_2018() { help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously", ident = ident, thing = b.descr())) } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 581756dc6bf..6fa9110fedb 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -605,6 +605,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { assert!(force || !record_used); // `record_used` implies `force` assert!(macro_kind.is_none() || !is_import); // `is_import` implies no macro kind + let rust_2015 = ident.span.rust_2015(); ident = ident.modern(); // Make sure `self`, `super` etc produce an error when passed to here. @@ -696,7 +697,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } } WhereToResolve::MacroUsePrelude => { - if use_prelude || self.session.rust_2015() { + if use_prelude || rust_2015 { match self.macro_use_prelude.get(&ident.name).cloned() { Some(binding) => Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)), @@ -725,7 +726,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } } WhereToResolve::LegacyPluginHelpers => { - if (use_prelude || self.session.rust_2015()) && + if (use_prelude || rust_2015) && self.session.plugin_attributes.borrow().iter() .any(|(name, _)| ident.name == &**name) { let binding = (Def::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e2f09affd4f..c82ebd6aa51 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -43,7 +43,7 @@ use ast::{BinOpKind, UnOp}; use ast::{RangeEnd, RangeSyntax}; use {ast, attr}; use source_map::{self, SourceMap, Spanned, respan}; -use syntax_pos::{self, Span, MultiSpan, BytePos, FileName, edition::Edition}; +use syntax_pos::{self, Span, MultiSpan, BytePos, FileName}; use errors::{self, Applicability, DiagnosticBuilder, DiagnosticId}; use parse::{self, SeqSep, classify, token}; use parse::lexer::TokenAndSpan; @@ -1404,11 +1404,7 @@ impl<'a> Parser<'a> { // definition... // We don't allow argument names to be left off in edition 2018. - if p.span.edition() >= Edition::Edition2018 { - p.parse_arg_general(true) - } else { - p.parse_arg_general(false) - } + p.parse_arg_general(p.span.rust_2018()) })?; generics.where_clause = self.parse_where_clause()?; @@ -1601,9 +1597,9 @@ impl<'a> Parser<'a> { impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds) } else if self.check_keyword(keywords::Dyn) && - (self.span.edition() == Edition::Edition2018 || + (self.span.rust_2018() || self.look_ahead(1, |t| t.can_begin_bound() && - !can_continue_type_after_non_fn_ident(t))) { + !can_continue_type_after_non_fn_ident(t))) { self.bump(); // `dyn` // Always parse bounds greedily for better error recovery. let bounds = self.parse_generic_bounds()?; @@ -2084,8 +2080,9 @@ impl<'a> Parser<'a> { let lo = self.meta_var_span.unwrap_or(self.span); let mut segments = Vec::new(); + let mod_sep_ctxt = self.span.ctxt(); if self.eat(&token::ModSep) { - segments.push(PathSegment::crate_root(lo.shrink_to_lo())); + segments.push(PathSegment::crate_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); } self.parse_path_segments(&mut segments, style, enable_warning)?; @@ -2423,8 +2420,7 @@ impl<'a> Parser<'a> { hi = path.span; return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs)); } - if self.span.edition() >= Edition::Edition2018 && - self.check_keyword(keywords::Async) + if self.span.rust_2018() && self.check_keyword(keywords::Async) { if self.is_async_block() { // check for `async {` and `async move {` return self.parse_async_block(attrs); @@ -3440,7 +3436,7 @@ impl<'a> Parser<'a> { } else { Movability::Movable }; - let asyncness = if self.span.edition() >= Edition::Edition2018 { + let asyncness = if self.span.rust_2018() { self.parse_asyncness() } else { IsAsync::NotAsync @@ -4562,9 +4558,7 @@ impl<'a> Parser<'a> { fn is_try_block(&mut self) -> bool { self.token.is_keyword(keywords::Try) && self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) && - - self.span.edition() >= Edition::Edition2018 && - + self.span.rust_2018() && // prevent `while try {} {}`, `if try {} {} else {}`, etc. !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) } @@ -7648,8 +7642,11 @@ impl<'a> Parser<'a> { self.check(&token::BinOp(token::Star)) || self.is_import_coupler() { // `use *;` or `use ::*;` or `use {...};` or `use ::{...};` + let mod_sep_ctxt = self.span.ctxt(); if self.eat(&token::ModSep) { - prefix.segments.push(PathSegment::crate_root(lo.shrink_to_lo())); + prefix.segments.push( + PathSegment::crate_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)) + ); } if self.eat(&token::BinOp(token::Star)) { diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index a780a38ff96..65f6d27239b 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -325,6 +325,16 @@ impl Span { |einfo| einfo.edition) } + #[inline] + pub fn rust_2015(&self) -> bool { + self.edition() == edition::Edition::Edition2015 + } + + #[inline] + pub fn rust_2018(&self) -> bool { + self.edition() >= edition::Edition::Edition2018 + } + /// Return the source callee. /// /// Returns `None` if the supplied span has no expansion trace, diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 361353c82e2..e333a4f2176 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -12,7 +12,6 @@ //! allows bidirectional lookup; i.e. given a value, one can easily find the //! type, and vice versa. -use edition::Edition; use hygiene::SyntaxContext; use {Span, DUMMY_SP, GLOBALS}; @@ -444,7 +443,7 @@ impl Ident { pub fn is_unused_keyword(self) -> bool { // Note: `span.edition()` is relatively expensive, don't call it unless necessary. self.name >= keywords::Abstract.name() && self.name <= keywords::Yield.name() || - self.name.is_unused_keyword_2018() && self.span.edition() == Edition::Edition2018 + self.name.is_unused_keyword_2018() && self.span.rust_2018() } /// Returns `true` if the token is either a special identifier or a keyword. diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/edition-imports-2015.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/edition-imports-2015.rs new file mode 100644 index 00000000000..5bb818f7d23 --- /dev/null +++ b/src/test/ui-fulldeps/proc-macro/auxiliary/edition-imports-2015.rs @@ -0,0 +1,19 @@ +// edition:2015 +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Derive2015)] +pub fn derive_2015(_: TokenStream) -> TokenStream { + " + use import::Path; + + fn check_absolute() { + let x = ::absolute::Path; + } + ".parse().unwrap() +} diff --git a/src/test/ui-fulldeps/proc-macro/edition-imports-2018.rs b/src/test/ui-fulldeps/proc-macro/edition-imports-2018.rs new file mode 100644 index 00000000000..f8d6bc5e078 --- /dev/null +++ b/src/test/ui-fulldeps/proc-macro/edition-imports-2018.rs @@ -0,0 +1,24 @@ +// compile-pass +// edition:2018 +// aux-build:edition-imports-2015.rs + +#[macro_use] +extern crate edition_imports_2015; + +mod import { + pub struct Path; +} +mod absolute { + pub struct Path; +} + +mod check { + #[derive(Derive2015)] // OK + struct S; + + fn check() { + Path; + } +} + +fn main() {} diff --git a/src/test/ui/editions/auxiliary/absolute.rs b/src/test/ui/editions/auxiliary/absolute.rs new file mode 100644 index 00000000000..d596f97355f --- /dev/null +++ b/src/test/ui/editions/auxiliary/absolute.rs @@ -0,0 +1 @@ +pub struct Path; diff --git a/src/test/ui/editions/auxiliary/edition-imports-2015.rs b/src/test/ui/editions/auxiliary/edition-imports-2015.rs new file mode 100644 index 00000000000..fb1a89d4022 --- /dev/null +++ b/src/test/ui/editions/auxiliary/edition-imports-2015.rs @@ -0,0 +1,17 @@ +// edition:2015 + +#[macro_export] +macro_rules! gen_imports { () => { + use import::Path; + // use std::collections::LinkedList; // FIXME + + fn check_absolute() { + ::absolute::Path; + // ::std::collections::LinkedList::::new(); // FIXME + } +}} + +#[macro_export] +macro_rules! gen_glob { () => { + use *; +}} diff --git a/src/test/ui/editions/auxiliary/edition-imports-2018.rs b/src/test/ui/editions/auxiliary/edition-imports-2018.rs new file mode 100644 index 00000000000..b08dc499a0d --- /dev/null +++ b/src/test/ui/editions/auxiliary/edition-imports-2018.rs @@ -0,0 +1,17 @@ +// edition:2018 + +#[macro_export] +macro_rules! gen_imports { () => { + use import::Path; + use std::collections::LinkedList; + + fn check_absolute() { + ::absolute::Path; + ::std::collections::LinkedList::::new(); + } +}} + +#[macro_export] +macro_rules! gen_glob { () => { + use *; +}} diff --git a/src/test/ui/editions/edition-imports-2015.rs b/src/test/ui/editions/edition-imports-2015.rs new file mode 100644 index 00000000000..b89ca28e279 --- /dev/null +++ b/src/test/ui/editions/edition-imports-2015.rs @@ -0,0 +1,28 @@ +// edition:2015 +// compile-flags:--extern absolute +// aux-build:edition-imports-2018.rs +// aux-build:absolute.rs + +#![feature(uniform_paths)] + +#[macro_use] +extern crate edition_imports_2018; + +mod check { + mod import { + pub struct Path; + } + + gen_imports!(); // OK + + fn check() { + Path; + LinkedList::::new(); + } +} + +mod check_glob { + gen_glob!(); //~ ERROR cannot glob-import all possible crates +} + +fn main() {} diff --git a/src/test/ui/editions/edition-imports-2015.stderr b/src/test/ui/editions/edition-imports-2015.stderr new file mode 100644 index 00000000000..fb6b2e64ef5 --- /dev/null +++ b/src/test/ui/editions/edition-imports-2015.stderr @@ -0,0 +1,10 @@ +error: cannot glob-import all possible crates + --> $DIR/edition-imports-2015.rs:25:5 + | +LL | gen_glob!(); //~ ERROR cannot glob-import all possible crates + | ^^^^^^^^^^^^ + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/editions/edition-imports-2018.rs b/src/test/ui/editions/edition-imports-2018.rs new file mode 100644 index 00000000000..cef4ce3bf16 --- /dev/null +++ b/src/test/ui/editions/edition-imports-2018.rs @@ -0,0 +1,33 @@ +// compile-pass +// edition:2018 +// aux-build:edition-imports-2015.rs + +#[macro_use] +extern crate edition_imports_2015; + +mod import { + pub struct Path; +} +mod absolute { + pub struct Path; +} + +mod check { + gen_imports!(); // OK + + fn check() { + Path; + // LinkedList::::new(); // FIXME + } +} + +mod check_glob { + gen_glob!(); // OK + + fn check() { + import::Path; + absolute::Path; + } +} + +fn main() {} From c06e69ee70bf1fec4630458d8e4417efcabe0424 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 24 Nov 2018 15:07:03 +0300 Subject: [PATCH 0287/1984] resolve: Fallback to uniform paths in 2015 imports used from global 2018 edition --- src/librustc_resolve/build_reduced_graph.rs | 5 +- src/librustc_resolve/lib.rs | 26 ++++- src/librustc_resolve/macros.rs | 102 ++++++++++++------ .../auxiliary/edition-imports-2015.rs | 15 ++- src/test/ui/editions/edition-imports-2018.rs | 2 +- .../edition-imports-virtual-2015-ambiguity.rs | 18 ++++ ...tion-imports-virtual-2015-ambiguity.stderr | 21 ++++ .../edition-imports-virtual-2015-gated.rs | 12 +++ .../edition-imports-virtual-2015-gated.stderr | 22 ++++ 9 files changed, 186 insertions(+), 37 deletions(-) create mode 100644 src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs create mode 100644 src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr create mode 100644 src/test/ui/editions/edition-imports-virtual-2015-gated.rs create mode 100644 src/test/ui/editions/edition-imports-virtual-2015-gated.stderr diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 3f0780191fb..2966e9ec9d9 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -132,9 +132,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // so prefixes are prepended with crate root segment if necessary. // The root is prepended lazily, when the first non-empty prefix or terminating glob // appears, so imports in braced groups can have roots prepended independently. + // 2015 identifiers used on global 2018 edition enter special "virtual 2015 mode", don't + // get crate root prepended, but get special treatment during in-scope resolution instead. let is_glob = if let ast::UseTreeKind::Glob = use_tree.kind { true } else { false }; let crate_root = match prefix_iter.peek() { - Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => { + Some(seg) if !seg.ident.is_path_segment_keyword() && + seg.ident.span.rust_2015() && self.session.rust_2015() => { Some(seg.ident.span.ctxt()) } None if is_glob && use_tree.span.rust_2015() => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2e7ed80c91b..07ded5c6723 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -13,6 +13,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(crate_visibility_modifier)] +#![feature(label_break_value)] #![feature(nll)] #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] @@ -2191,28 +2192,45 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { fn resolve_ident_in_module( &mut self, module: ModuleOrUniformRoot<'a>, - mut ident: Ident, + ident: Ident, ns: Namespace, parent_scope: Option<&ParentScope<'a>>, record_used: bool, path_span: Span ) -> Result<&'a NameBinding<'a>, Determinacy> { - ident.span = ident.span.modern(); + self.resolve_ident_in_module_ext( + module, ident, ns, parent_scope, record_used, path_span + ).map_err(|(determinacy, _)| determinacy) + } + + fn resolve_ident_in_module_ext( + &mut self, + module: ModuleOrUniformRoot<'a>, + mut ident: Ident, + ns: Namespace, + parent_scope: Option<&ParentScope<'a>>, + record_used: bool, + path_span: Span + ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { let orig_current_module = self.current_module; match module { ModuleOrUniformRoot::Module(module) => { + ident.span = ident.span.modern(); if let Some(def) = ident.span.adjust(module.expansion) { self.current_module = self.macro_def_scope(def); } } ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude) => { + ident.span = ident.span.modern(); ident.span.adjust(Mark::root()); } - _ => {} + ModuleOrUniformRoot::UniformRoot(UniformRootKind::CurrentScope) => { + // No adjustments + } } let result = self.resolve_ident_in_module_unadjusted_ext( module, ident, ns, parent_scope, false, record_used, path_span, - ).map_err(|(determinacy, _)| determinacy); + ); self.current_module = orig_current_module; result } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 6fa9110fedb..bc3700b8c63 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -526,7 +526,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // `foo::bar!(); or `foo!();`) and also for import paths on 2018 edition. crate fn early_resolve_ident_in_lexical_scope( &mut self, - mut ident: Ident, + orig_ident: Ident, ns: Namespace, macro_kind: Option, is_import: bool, @@ -582,6 +582,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { enum WhereToResolve<'a> { DeriveHelpers, MacroRules(LegacyScope<'a>), + CrateRoot, Module(Module<'a>), MacroUsePrelude, BuiltinMacros, @@ -605,8 +606,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> { assert!(force || !record_used); // `record_used` implies `force` assert!(macro_kind.is_none() || !is_import); // `is_import` implies no macro kind - let rust_2015 = ident.span.rust_2015(); - ident = ident.modern(); + let rust_2015 = orig_ident.span.rust_2015(); + let mut ident = orig_ident.modern(); // Make sure `self`, `super` etc produce an error when passed to here. if ident.is_path_segment_keyword() { @@ -627,10 +628,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let mut innermost_result: Option<(&NameBinding, Flags)> = None; // Go through all the scopes and try to resolve the name. - let mut where_to_resolve = if ns == MacroNS { - WhereToResolve::DeriveHelpers - } else { - WhereToResolve::Module(parent_scope.module) + let mut where_to_resolve = match ns { + _ if is_import && rust_2015 => WhereToResolve::CrateRoot, + TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module), + MacroNS => WhereToResolve::DeriveHelpers, }; let mut use_prelude = !parent_scope.module.no_implicit_prelude; let mut determinacy = Determinacy::Determined; @@ -668,6 +669,26 @@ impl<'a, 'cl> Resolver<'a, 'cl> { Err(Determinacy::Undetermined), _ => Err(Determinacy::Determined), } + WhereToResolve::CrateRoot => { + let root_ident = Ident::new(keywords::CrateRoot.name(), orig_ident.span); + let root_module = self.resolve_crate_root(root_ident); + let binding = self.resolve_ident_in_module_ext( + ModuleOrUniformRoot::Module(root_module), + orig_ident, + ns, + None, + record_used, + path_span, + ); + match binding { + Ok(binding) => Ok((binding, Flags::MODULE)), + Err((Determinacy::Undetermined, Weak::No)) => + return Err(Determinacy::determined(force)), + Err((Determinacy::Undetermined, Weak::Yes)) => + Err(Determinacy::Undetermined), + Err((Determinacy::Determined, _)) => Err(Determinacy::Determined), + } + } WhereToResolve::Module(module) => { let orig_current_module = mem::replace(&mut self.current_module, module); let binding = self.resolve_ident_in_module_unadjusted_ext( @@ -816,7 +837,11 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } else if innermost_flags.contains(Flags::MACRO_RULES) && flags.contains(Flags::MODULE) && !self.disambiguate_legacy_vs_modern(innermost_binding, - binding) { + binding) || + flags.contains(Flags::MACRO_RULES) && + innermost_flags.contains(Flags::MODULE) && + !self.disambiguate_legacy_vs_modern(binding, + innermost_binding) { Some(AmbiguityKind::LegacyVsModern) } else if innermost_binding.is_glob_import() { Some(AmbiguityKind::GlobVsOuter) @@ -867,6 +892,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> { LegacyScope::Empty => WhereToResolve::Module(parent_scope.module), LegacyScope::Uninitialized => unreachable!(), } + WhereToResolve::CrateRoot => match ns { + TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module), + MacroNS => WhereToResolve::DeriveHelpers, + } WhereToResolve::Module(module) => { match self.hygienic_lexical_parent(module, &mut ident.span) { Some(parent_module) => WhereToResolve::Module(parent_module), @@ -899,30 +928,43 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // The first found solution was the only one, return it. if let Some((binding, flags)) = innermost_result { - if is_import && !self.session.features_untracked().uniform_paths { - // We get to here only if there's no ambiguity, in ambiguous cases an error will - // be reported anyway, so there's no reason to report an additional feature error. - // The `binding` can actually be introduced by something other than `--extern`, - // but its `Def` should coincide with a crate passed with `--extern` - // (otherwise there would be ambiguity) and we can skip feature error in this case. - if ns != TypeNS || !use_prelude || - self.extern_prelude_get(ident, true).is_none() { - let msg = "imports can only refer to extern crate names \ - passed with `--extern` on stable channel"; - let mut err = feature_err(&self.session.parse_sess, "uniform_paths", - ident.span, GateIssue::Language, msg); - - let what = self.binding_description(binding, ident, - flags.contains(Flags::MISC_FROM_PRELUDE)); - let note_msg = format!("this import refers to {what}", what = what); - if binding.span.is_dummy() { - err.note(¬e_msg); - } else { - err.span_note(binding.span, ¬e_msg); - err.span_label(binding.span, "not an extern crate passed with `--extern`"); + // We get to here only if there's no ambiguity, in ambiguous cases an error will + // be reported anyway, so there's no reason to report an additional feature error. + // The `binding` can actually be introduced by something other than `--extern`, + // but its `Def` should coincide with a crate passed with `--extern` + // (otherwise there would be ambiguity) and we can skip feature error in this case. + 'ok: { + if !is_import || self.session.features_untracked().uniform_paths { + break 'ok; + } + if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() { + break 'ok; + } + if rust_2015 { + let root_ident = Ident::new(keywords::CrateRoot.name(), orig_ident.span); + let root_module = self.resolve_crate_root(root_ident); + if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module), + orig_ident, ns, None, false, path_span) + .is_ok() { + break 'ok; } - err.emit(); } + + let msg = "imports can only refer to extern crate names \ + passed with `--extern` on stable channel"; + let mut err = feature_err(&self.session.parse_sess, "uniform_paths", + ident.span, GateIssue::Language, msg); + + let what = self.binding_description(binding, ident, + flags.contains(Flags::MISC_FROM_PRELUDE)); + let note_msg = format!("this import refers to {what}", what = what); + if binding.span.is_dummy() { + err.note(¬e_msg); + } else { + err.span_note(binding.span, ¬e_msg); + err.span_label(binding.span, "not an extern crate passed with `--extern`"); + } + err.emit(); } return Ok(binding); diff --git a/src/test/ui/editions/auxiliary/edition-imports-2015.rs b/src/test/ui/editions/auxiliary/edition-imports-2015.rs index fb1a89d4022..d7985d12dae 100644 --- a/src/test/ui/editions/auxiliary/edition-imports-2015.rs +++ b/src/test/ui/editions/auxiliary/edition-imports-2015.rs @@ -3,7 +3,7 @@ #[macro_export] macro_rules! gen_imports { () => { use import::Path; - // use std::collections::LinkedList; // FIXME + use std::collections::LinkedList; fn check_absolute() { ::absolute::Path; @@ -15,3 +15,16 @@ macro_rules! gen_imports { () => { macro_rules! gen_glob { () => { use *; }} + +#[macro_export] +macro_rules! gen_gated { () => { + fn check_gated() { + enum E { A } + use E::*; + } +}} + +#[macro_export] +macro_rules! gen_ambiguous { () => { + use Ambiguous; +}} diff --git a/src/test/ui/editions/edition-imports-2018.rs b/src/test/ui/editions/edition-imports-2018.rs index cef4ce3bf16..989170d041f 100644 --- a/src/test/ui/editions/edition-imports-2018.rs +++ b/src/test/ui/editions/edition-imports-2018.rs @@ -17,7 +17,7 @@ mod check { fn check() { Path; - // LinkedList::::new(); // FIXME + LinkedList::::new(); } } diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs new file mode 100644 index 00000000000..2527b30f07b --- /dev/null +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs @@ -0,0 +1,18 @@ +// edition:2018 +// aux-build:edition-imports-2015.rs +// error-pattern: `Ambiguous` is ambiguous + +#[macro_use] +extern crate edition_imports_2015; + +pub struct Ambiguous {} + +mod check { + pub struct Ambiguous {} + + fn check() { + gen_ambiguous!(); + } +} + +fn main() {} diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr new file mode 100644 index 00000000000..8e0b135121e --- /dev/null +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr @@ -0,0 +1,21 @@ +error[E0659]: `Ambiguous` is ambiguous (name vs any other name during import resolution) + --> <::edition_imports_2015::gen_ambiguous macros>:1:15 + | +LL | ( ) => { use Ambiguous ; } + | ^^^^^^^^^ ambiguous name + | +note: `Ambiguous` could refer to the struct defined here + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:8:1 + | +LL | pub struct Ambiguous {} + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: `Ambiguous` could also refer to the struct defined here + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:5 + | +LL | pub struct Ambiguous {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `self::Ambiguous` to refer to this struct unambiguously + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/editions/edition-imports-virtual-2015-gated.rs b/src/test/ui/editions/edition-imports-virtual-2015-gated.rs new file mode 100644 index 00000000000..a1bf4f5eb51 --- /dev/null +++ b/src/test/ui/editions/edition-imports-virtual-2015-gated.rs @@ -0,0 +1,12 @@ +// edition:2018 +// aux-build:edition-imports-2015.rs +// error-pattern: imports can only refer to extern crate names passed with `--extern` + +#[macro_use] +extern crate edition_imports_2015; + +mod check { + gen_gated!(); +} + +fn main() {} diff --git a/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr b/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr new file mode 100644 index 00000000000..7c1837e3f56 --- /dev/null +++ b/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr @@ -0,0 +1,22 @@ +error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130) + --> <::edition_imports_2015::gen_gated macros>:1:50 + | +LL | ( ) => { fn check_gated ( ) { enum E { A } use E :: * ; } } + | ^ + | + ::: $DIR/edition-imports-virtual-2015-gated.rs:9:5 + | +LL | gen_gated!(); + | ------------- not an extern crate passed with `--extern` + | + = help: add #![feature(uniform_paths)] to the crate attributes to enable +note: this import refers to the enum defined here + --> $DIR/edition-imports-virtual-2015-gated.rs:9:5 + | +LL | gen_gated!(); + | ^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From 5e121756ef003f13b9dbb6a44b8bc4dce87b84a8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 24 Nov 2018 19:14:05 +0300 Subject: [PATCH 0288/1984] resolve: Generalize `early_resolve_ident_in_lexical_scope` slightly Flatten `ModuleOrUniformRoot` variants --- src/librustc_resolve/lib.rs | 51 ++++++++------- src/librustc_resolve/macros.rs | 24 +++---- src/librustc_resolve/resolve_imports.rs | 85 ++++++++++++------------- 3 files changed, 78 insertions(+), 82 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 07ded5c6723..bc0e8a56157 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -102,6 +102,12 @@ enum Weak { No, } +enum ScopeSet { + Import(Namespace), + Macro(MacroKind), + Module, +} + /// A free importable items suggested in case of resolution failure. struct ImportSuggestion { path: Path, @@ -997,22 +1003,19 @@ impl<'a> LexicalScopeBinding<'a> { } } - -#[derive(Clone, Copy, PartialEq, Debug)] -enum UniformRootKind { - CurrentScope, - ExternPrelude, -} - #[derive(Copy, Clone, Debug)] enum ModuleOrUniformRoot<'a> { /// Regular module. Module(Module<'a>), - /// This "virtual module" denotes either resolution in extern prelude - /// for paths starting with `::` on 2018 edition or `extern::`, - /// or resolution in current scope for single-segment imports. - UniformRoot(UniformRootKind), + /// Virtual module that denotes resolution in extern prelude. + /// Used for paths starting with `::` on 2018 edition or `extern::`. + ExternPrelude, + + /// Virtual module that denotes resolution in current scope. + /// Used only for resolving single-segment imports. The reason it exists is that import paths + /// are always split into two parts, the first of which should be some kind of module. + CurrentScope, } impl<'a> PartialEq for ModuleOrUniformRoot<'a> { @@ -1020,8 +1023,8 @@ impl<'a> PartialEq for ModuleOrUniformRoot<'a> { match (*self, *other) { (ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) => ptr::eq(lhs, rhs), - (ModuleOrUniformRoot::UniformRoot(lhs), ModuleOrUniformRoot::UniformRoot(rhs)) => - lhs == rhs, + (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) => true, + (ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true, _ => false, } } @@ -1758,8 +1761,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { error_callback(self, span, ResolutionError::FailedToResolve(msg)); Def::Err } - PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) | - PathResult::Indeterminate => unreachable!(), + PathResult::Module(..) | PathResult::Indeterminate => unreachable!(), PathResult::Failed(span, msg, _) => { error_callback(self, span, ResolutionError::FailedToResolve(&msg)); Def::Err @@ -2220,11 +2222,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.current_module = self.macro_def_scope(def); } } - ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude) => { + ModuleOrUniformRoot::ExternPrelude => { ident.span = ident.span.modern(); ident.span.adjust(Mark::root()); } - ModuleOrUniformRoot::UniformRoot(UniformRootKind::CurrentScope) => { + ModuleOrUniformRoot::CurrentScope => { // No adjustments } } @@ -3667,8 +3669,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); err_path_resolution() } - PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) | - PathResult::Failed(..) => return None, + PathResult::Module(..) | PathResult::Failed(..) => return None, PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"), }; @@ -3787,8 +3788,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } if name == keywords::Extern.name() || name == keywords::CrateRoot.name() && ident.span.rust_2018() { - module = - Some(ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude)); + module = Some(ModuleOrUniformRoot::ExternPrelude); continue; } if name == keywords::CrateRoot.name() || @@ -3821,9 +3821,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.resolve_ident_in_module(module, ident, ns, None, record_used, path_span) } else if opt_ns.is_none() || opt_ns == Some(MacroNS) { assert!(ns == TypeNS); - self.early_resolve_ident_in_lexical_scope(ident, ns, None, opt_ns.is_none(), - parent_scope, record_used, record_used, - path_span) + let scopes = if opt_ns.is_none() { ScopeSet::Import(ns) } else { ScopeSet::Module }; + self.early_resolve_ident_in_lexical_scope(ident, scopes, parent_scope, record_used, + record_used, path_span) } else { let record_used_id = if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None }; @@ -3912,8 +3912,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { PathResult::Module(match module { Some(module) => module, - None if path.is_empty() => - ModuleOrUniformRoot::UniformRoot(UniformRootKind::CurrentScope), + None if path.is_empty() => ModuleOrUniformRoot::CurrentScope, _ => span_bug!(path_span, "resolve_path: non-empty path `{:?}` has no module", path), }) } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index bc3700b8c63..5493913fd81 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -9,11 +9,11 @@ // except according to those terms. use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc}; -use {CrateLint, Resolver, ResolutionError, Segment, Weak}; -use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding}; +use {CrateLint, Resolver, ResolutionError, ScopeSet, Weak}; +use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding}; use {is_known_tool, resolve_error}; use ModuleOrUniformRoot; -use Namespace::{self, *}; +use Namespace::*; use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport}; use resolve_imports::ImportResolver; use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex, @@ -502,7 +502,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { def } else { let binding = self.early_resolve_ident_in_lexical_scope( - path[0].ident, MacroNS, Some(kind), false, parent_scope, false, force, path_span + path[0].ident, ScopeSet::Macro(kind), parent_scope, false, force, path_span ); match binding { Ok(..) => {} @@ -527,9 +527,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { crate fn early_resolve_ident_in_lexical_scope( &mut self, orig_ident: Ident, - ns: Namespace, - macro_kind: Option, - is_import: bool, + scope_set: ScopeSet, parent_scope: &ParentScope<'a>, record_used: bool, force: bool, @@ -605,8 +603,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } assert!(force || !record_used); // `record_used` implies `force` - assert!(macro_kind.is_none() || !is_import); // `is_import` implies no macro kind - let rust_2015 = orig_ident.span.rust_2015(); let mut ident = orig_ident.modern(); // Make sure `self`, `super` etc produce an error when passed to here. @@ -628,6 +624,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let mut innermost_result: Option<(&NameBinding, Flags)> = None; // Go through all the scopes and try to resolve the name. + let rust_2015 = orig_ident.span.rust_2015(); + let (ns, macro_kind, is_import) = match scope_set { + ScopeSet::Import(ns) => (ns, None, true), + ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false), + ScopeSet::Module => (TypeNS, None, false), + }; let mut where_to_resolve = match ns { _ if is_import && rust_2015 => WhereToResolve::CrateRoot, TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module), @@ -1041,7 +1043,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let macro_resolutions = mem::replace(&mut *module.single_segment_macro_resolutions.borrow_mut(), Vec::new()); for (ident, kind, parent_scope, initial_binding) in macro_resolutions { - match self.early_resolve_ident_in_lexical_scope(ident, MacroNS, Some(kind), false, + match self.early_resolve_ident_in_lexical_scope(ident, ScopeSet::Macro(kind), &parent_scope, true, true, ident.span) { Ok(binding) => { let initial_def = initial_binding.map(|initial_binding| { @@ -1067,7 +1069,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new()); for (ident, parent_scope) in builtin_attrs { let _ = self.early_resolve_ident_in_lexical_scope( - ident, MacroNS, Some(MacroKind::Attr), false, &parent_scope, true, true, ident.span + ident, ScopeSet::Macro(MacroKind::Attr), &parent_scope, true, true, ident.span ); } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 52e3e54b9f9..47bfadf932e 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -11,7 +11,7 @@ use self::ImportDirectiveSubclass::*; use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc}; -use {CrateLint, Module, ModuleOrUniformRoot, PerNS, UniformRootKind, Weak}; +use {CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, Weak}; use Namespace::{self, TypeNS, MacroNS}; use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError}; use {Resolver, Segment}; @@ -162,45 +162,42 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { let module = match module { ModuleOrUniformRoot::Module(module) => module, - ModuleOrUniformRoot::UniformRoot(uniform_root_kind) => { + ModuleOrUniformRoot::ExternPrelude => { assert!(!restricted_shadowing); - match uniform_root_kind { - UniformRootKind::ExternPrelude => { - return if let Some(binding) = self.extern_prelude_get(ident, !record_used) { - Ok(binding) - } else if !self.graph_root.unresolved_invocations.borrow().is_empty() { - // Macro-expanded `extern crate` items can add names to extern prelude. - Err((Undetermined, Weak::No)) - } else { - Err((Determined, Weak::No)) - } - } - UniformRootKind::CurrentScope => { - let parent_scope = - parent_scope.expect("no parent scope for a single-segment import"); - - if ns == TypeNS { - if ident.name == keywords::Crate.name() || - ident.name == keywords::DollarCrate.name() { - let module = self.resolve_crate_root(ident); - let binding = (module, ty::Visibility::Public, - module.span, Mark::root()) - .to_name_binding(self.arenas); - return Ok(binding); - } else if ident.name == keywords::Super.name() || - ident.name == keywords::SelfValue.name() { - // FIXME: Implement these with renaming requirements so that e.g. - // `use super;` doesn't work, but `use super as name;` does. - // Fall through here to get an error from `early_resolve_...`. - } - } - - let binding = self.early_resolve_ident_in_lexical_scope( - ident, ns, None, true, parent_scope, record_used, record_used, path_span - ); - return binding.map_err(|determinacy| (determinacy, Weak::No)); + return if let Some(binding) = self.extern_prelude_get(ident, !record_used) { + Ok(binding) + } else if !self.graph_root.unresolved_invocations.borrow().is_empty() { + // Macro-expanded `extern crate` items can add names to extern prelude. + Err((Undetermined, Weak::No)) + } else { + Err((Determined, Weak::No)) + } + } + ModuleOrUniformRoot::CurrentScope => { + assert!(!restricted_shadowing); + let parent_scope = + parent_scope.expect("no parent scope for a single-segment import"); + + if ns == TypeNS { + if ident.name == keywords::Crate.name() || + ident.name == keywords::DollarCrate.name() { + let module = self.resolve_crate_root(ident); + let binding = (module, ty::Visibility::Public, + module.span, Mark::root()) + .to_name_binding(self.arenas); + return Ok(binding); + } else if ident.name == keywords::Super.name() || + ident.name == keywords::SelfValue.name() { + // FIXME: Implement these with renaming requirements so that e.g. + // `use super;` doesn't work, but `use super as name;` does. + // Fall through here to get an error from `early_resolve_...`. } } + + let binding = self.early_resolve_ident_in_lexical_scope( + ident, ScopeSet::Import(ns), parent_scope, record_used, record_used, path_span + ); + return binding.map_err(|determinacy| (determinacy, Weak::No)); } }; @@ -333,7 +330,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { } let module = match glob_import.imported_module.get() { Some(ModuleOrUniformRoot::Module(module)) => module, - Some(ModuleOrUniformRoot::UniformRoot(_)) => continue, + Some(_) => continue, None => return Err((Undetermined, Weak::Yes)), }; let (orig_current_module, mut ident) = (self.current_module, ident.modern()); @@ -966,9 +963,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { return if all_ns_failed { let resolutions = match module { - ModuleOrUniformRoot::Module(module) => - Some(module.resolutions.borrow()), - ModuleOrUniformRoot::UniformRoot(_) => None, + ModuleOrUniformRoot::Module(module) => Some(module.resolutions.borrow()), + _ => None, }; let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter()); let names = resolutions.filter_map(|(&(ref i, _), resolution)| { @@ -1006,7 +1002,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { format!("no `{}` in the root{}", ident, lev_suggestion) } } - ModuleOrUniformRoot::UniformRoot(_) => { + _ => { if !ident.is_path_segment_keyword() { format!("no `{}` external crate{}", ident, lev_suggestion) } else { @@ -1107,9 +1103,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) { let module = match directive.imported_module.get().unwrap() { ModuleOrUniformRoot::Module(module) => module, - ModuleOrUniformRoot::UniformRoot(_) => { - self.session.span_err(directive.span, - "cannot glob-import all possible crates"); + _ => { + self.session.span_err(directive.span, "cannot glob-import all possible crates"); return; } }; From d1862b419616d1198b89f57d4e1416f85d4d2101 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 25 Nov 2018 00:25:03 +0300 Subject: [PATCH 0289/1984] resolve: Fallback to extern prelude in 2015 imports used from global 2018 edition --- src/librustc_resolve/lib.rs | 22 +++++++++++++--- src/librustc_resolve/macros.rs | 26 ++++++++++++++----- src/librustc_resolve/resolve_imports.rs | 9 +++++++ .../auxiliary/edition-imports-2015.rs | 3 ++- src/test/ui/editions/edition-imports-2018.rs | 8 +----- .../ui/editions/edition-imports-2018.stderr | 10 +++++++ .../edition-imports-virtual-2015-ambiguity.rs | 9 ++++--- ...tion-imports-virtual-2015-ambiguity.stderr | 24 ++++++++++++++--- 8 files changed, 86 insertions(+), 25 deletions(-) create mode 100644 src/test/ui/editions/edition-imports-2018.stderr diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index bc0e8a56157..0be9881f910 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -104,6 +104,7 @@ enum Weak { enum ScopeSet { Import(Namespace), + AbsolutePath(Namespace), Macro(MacroKind), Module, } @@ -1008,6 +1009,9 @@ enum ModuleOrUniformRoot<'a> { /// Regular module. Module(Module<'a>), + /// Virtual module that denotes resolution in crate root with fallback to extern prelude. + CrateRootAndExternPrelude, + /// Virtual module that denotes resolution in extern prelude. /// Used for paths starting with `::` on 2018 edition or `extern::`. ExternPrelude, @@ -1021,9 +1025,11 @@ enum ModuleOrUniformRoot<'a> { impl<'a> PartialEq for ModuleOrUniformRoot<'a> { fn eq(&self, other: &Self) -> bool { match (*self, *other) { - (ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) => - ptr::eq(lhs, rhs), - (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) => true, + (ModuleOrUniformRoot::Module(lhs), + ModuleOrUniformRoot::Module(rhs)) => ptr::eq(lhs, rhs), + (ModuleOrUniformRoot::CrateRootAndExternPrelude, + ModuleOrUniformRoot::CrateRootAndExternPrelude) | + (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) | (ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true, _ => false, } @@ -1243,6 +1249,7 @@ struct UseError<'a> { #[derive(Clone, Copy, PartialEq, Debug)] enum AmbiguityKind { Import, + AbsolutePath, BuiltinAttr, DeriveHelper, LegacyHelperVsPrelude, @@ -1258,6 +1265,8 @@ impl AmbiguityKind { match self { AmbiguityKind::Import => "name vs any other name during import resolution", + AmbiguityKind::AbsolutePath => + "name in the crate root vs extern crate during absolute path resolution", AmbiguityKind::BuiltinAttr => "built-in attribute vs any other name", AmbiguityKind::DeriveHelper => @@ -2226,6 +2235,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { ident.span = ident.span.modern(); ident.span.adjust(Mark::root()); } + ModuleOrUniformRoot::CrateRootAndExternPrelude | ModuleOrUniformRoot::CurrentScope => { // No adjustments } @@ -3791,6 +3801,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { module = Some(ModuleOrUniformRoot::ExternPrelude); continue; } + if name == keywords::CrateRoot.name() && + ident.span.rust_2015() && self.session.rust_2018() { + // `::a::b` from 2015 macro on 2018 global edition + module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude); + continue; + } if name == keywords::CrateRoot.name() || name == keywords::Crate.name() || name == keywords::DollarCrate.name() { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 5493913fd81..d306e9ebe32 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -625,13 +625,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // Go through all the scopes and try to resolve the name. let rust_2015 = orig_ident.span.rust_2015(); - let (ns, macro_kind, is_import) = match scope_set { - ScopeSet::Import(ns) => (ns, None, true), - ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false), - ScopeSet::Module => (TypeNS, None, false), + let (ns, macro_kind, is_import, is_absolute_path) = match scope_set { + ScopeSet::Import(ns) => (ns, None, true, false), + ScopeSet::AbsolutePath(ns) => (ns, None, false, true), + ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false, false), + ScopeSet::Module => (TypeNS, None, false, false), }; let mut where_to_resolve = match ns { - _ if is_import && rust_2015 => WhereToResolve::CrateRoot, + _ if is_absolute_path || is_import && rust_2015 => WhereToResolve::CrateRoot, TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module), MacroNS => WhereToResolve::DeriveHelpers, }; @@ -761,7 +762,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } } WhereToResolve::ExternPrelude => { - if use_prelude { + if use_prelude || is_absolute_path { match self.extern_prelude_get(ident, !record_used) { Some(binding) => Ok((binding, Flags::PRELUDE)), None => Err(Determinacy::determined( @@ -827,6 +828,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let ambiguity_error_kind = if is_import { Some(AmbiguityKind::Import) + } else if is_absolute_path { + Some(AmbiguityKind::AbsolutePath) } else if innermost_def == builtin || def == builtin { Some(AmbiguityKind::BuiltinAttr) } else if innermost_def == derive_helper || def == derive_helper { @@ -894,10 +897,18 @@ impl<'a, 'cl> Resolver<'a, 'cl> { LegacyScope::Empty => WhereToResolve::Module(parent_scope.module), LegacyScope::Uninitialized => unreachable!(), } - WhereToResolve::CrateRoot => match ns { + WhereToResolve::CrateRoot if is_import => match ns { TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module), MacroNS => WhereToResolve::DeriveHelpers, } + WhereToResolve::CrateRoot if is_absolute_path => match ns { + TypeNS => { + ident.span.adjust(Mark::root()); + WhereToResolve::ExternPrelude + } + ValueNS | MacroNS => break, + } + WhereToResolve::CrateRoot => unreachable!(), WhereToResolve::Module(module) => { match self.hygienic_lexical_parent(module, &mut ident.span) { Some(parent_module) => WhereToResolve::Module(parent_module), @@ -915,6 +926,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs, WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers, WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search + WhereToResolve::ExternPrelude if is_absolute_path => break, WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude, WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude, WhereToResolve::StdLibPrelude => match ns { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 47bfadf932e..3bfa862f0dc 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -162,6 +162,15 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { let module = match module { ModuleOrUniformRoot::Module(module) => module, + ModuleOrUniformRoot::CrateRootAndExternPrelude => { + assert!(!restricted_shadowing); + let parent_scope = self.dummy_parent_scope(); + let binding = self.early_resolve_ident_in_lexical_scope( + ident, ScopeSet::AbsolutePath(ns), &parent_scope, + record_used, record_used, path_span, + ); + return binding.map_err(|determinacy| (determinacy, Weak::No)); + } ModuleOrUniformRoot::ExternPrelude => { assert!(!restricted_shadowing); return if let Some(binding) = self.extern_prelude_get(ident, !record_used) { diff --git a/src/test/ui/editions/auxiliary/edition-imports-2015.rs b/src/test/ui/editions/auxiliary/edition-imports-2015.rs index d7985d12dae..c72331ca2e1 100644 --- a/src/test/ui/editions/auxiliary/edition-imports-2015.rs +++ b/src/test/ui/editions/auxiliary/edition-imports-2015.rs @@ -7,7 +7,7 @@ macro_rules! gen_imports { () => { fn check_absolute() { ::absolute::Path; - // ::std::collections::LinkedList::::new(); // FIXME + ::std::collections::LinkedList::::new(); } }} @@ -27,4 +27,5 @@ macro_rules! gen_gated { () => { #[macro_export] macro_rules! gen_ambiguous { () => { use Ambiguous; + type A = ::edition_imports_2015::Path; }} diff --git a/src/test/ui/editions/edition-imports-2018.rs b/src/test/ui/editions/edition-imports-2018.rs index 989170d041f..dcdbf0d050b 100644 --- a/src/test/ui/editions/edition-imports-2018.rs +++ b/src/test/ui/editions/edition-imports-2018.rs @@ -1,4 +1,3 @@ -// compile-pass // edition:2018 // aux-build:edition-imports-2015.rs @@ -22,12 +21,7 @@ mod check { } mod check_glob { - gen_glob!(); // OK - - fn check() { - import::Path; - absolute::Path; - } + gen_glob!(); //~ ERROR cannot glob-import all possible crates } fn main() {} diff --git a/src/test/ui/editions/edition-imports-2018.stderr b/src/test/ui/editions/edition-imports-2018.stderr new file mode 100644 index 00000000000..944f42ee045 --- /dev/null +++ b/src/test/ui/editions/edition-imports-2018.stderr @@ -0,0 +1,10 @@ +error: cannot glob-import all possible crates + --> $DIR/edition-imports-2018.rs:24:5 + | +LL | gen_glob!(); //~ ERROR cannot glob-import all possible crates + | ^^^^^^^^^^^^ + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs index 2527b30f07b..562d3c9e70f 100644 --- a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs @@ -1,9 +1,12 @@ // edition:2018 +// compile-flags:--extern edition_imports_2015 // aux-build:edition-imports-2015.rs // error-pattern: `Ambiguous` is ambiguous +// error-pattern: `edition_imports_2015` is ambiguous -#[macro_use] -extern crate edition_imports_2015; +mod edition_imports_2015 { + pub struct Path; +} pub struct Ambiguous {} @@ -11,7 +14,7 @@ mod check { pub struct Ambiguous {} fn check() { - gen_ambiguous!(); + edition_imports_2015::gen_ambiguous!(); } } diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr index 8e0b135121e..d0897d081c3 100644 --- a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr @@ -1,21 +1,37 @@ error[E0659]: `Ambiguous` is ambiguous (name vs any other name during import resolution) --> <::edition_imports_2015::gen_ambiguous macros>:1:15 | -LL | ( ) => { use Ambiguous ; } +LL | ( ) => { use Ambiguous ; type A = :: edition_imports_2015 :: Path ; } | ^^^^^^^^^ ambiguous name | note: `Ambiguous` could refer to the struct defined here - --> $DIR/edition-imports-virtual-2015-ambiguity.rs:8:1 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:1 | LL | pub struct Ambiguous {} | ^^^^^^^^^^^^^^^^^^^^^^^ note: `Ambiguous` could also refer to the struct defined here - --> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:5 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:14:5 | LL | pub struct Ambiguous {} | ^^^^^^^^^^^^^^^^^^^^^^^ = help: use `self::Ambiguous` to refer to this struct unambiguously -error: aborting due to previous error +error[E0659]: `edition_imports_2015` is ambiguous (name in the crate root vs extern crate during absolute path resolution) + --> <::edition_imports_2015::gen_ambiguous macros>:1:39 + | +LL | ( ) => { use Ambiguous ; type A = :: edition_imports_2015 :: Path ; } + | ^^^^^^^^^^^^^^^^^^^^ ambiguous name + | + = note: `edition_imports_2015` could refer to an extern crate passed with `--extern` + = help: use `::edition_imports_2015` to refer to this extern crate unambiguously +note: `edition_imports_2015` could also refer to the module defined here + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:7:1 + | +LL | / mod edition_imports_2015 { +LL | | pub struct Path; +LL | | } + | |_^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0659`. From 6f13708299c22cf8450e239c4ab06aada2d1cf07 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 25 Nov 2018 16:08:43 +0300 Subject: [PATCH 0290/1984] resolve: Suggest `crate::` for resolving ambiguities when appropriate More precise spans for ambiguities from macros --- src/librustc_resolve/lib.rs | 22 +++++++++++----- src/librustc_resolve/macros.rs | 25 +++++++++++-------- ...helper-attr-blocked-by-import-ambig.stderr | 2 +- .../proc-macro/ambiguous-builtin-attrs.stderr | 10 ++++---- .../proc-macro/derive-helper-shadowing.stderr | 2 +- .../edition-imports-virtual-2015-ambiguity.rs | 5 ++-- ...tion-imports-virtual-2015-ambiguity.stderr | 23 +++++++++-------- .../local-modularized-tricky-fail-1.rs | 1 + .../local-modularized-tricky-fail-1.stderr | 15 +++++------ src/test/ui/imports/macro-paths.stderr | 2 +- .../macros/restricted-shadowing-legacy.stderr | 24 ++++++++++++++++++ .../macros/restricted-shadowing-modern.stderr | 18 +++++++++++++ .../uniform-paths/ambiguity-macros.stderr | 2 +- .../rust-2018/uniform-paths/ambiguity.stderr | 2 +- .../block-scoped-shadow-nested.stderr | 2 +- .../uniform-paths/block-scoped-shadow.stderr | 6 ++--- 16 files changed, 111 insertions(+), 50 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0be9881f910..cbf82a80266 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1292,6 +1292,7 @@ impl AmbiguityKind { /// Miscellaneous bits of metadata for better ambiguity error reporting. #[derive(Clone, Copy, PartialEq)] enum AmbiguityErrorMisc { + SuggestCrate, SuggestSelf, FromPrelude, None, @@ -4870,12 +4871,21 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { `{ident}` to disambiguate", ident = ident)) } if b.is_extern_crate() && ident.span.rust_2018() { - help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously", - ident = ident, thing = b.descr())) - } - if misc == AmbiguityErrorMisc::SuggestSelf { - help_msgs.push(format!("use `self::{ident}` to refer to this {thing} unambiguously", - ident = ident, thing = b.descr())) + help_msgs.push(format!( + "use `::{ident}` to refer to this {thing} unambiguously", + ident = ident, thing = b.descr(), + )) + } + if misc == AmbiguityErrorMisc::SuggestCrate { + help_msgs.push(format!( + "use `crate::{ident}` to refer to this {thing} unambiguously", + ident = ident, thing = b.descr(), + )) + } else if misc == AmbiguityErrorMisc::SuggestSelf { + help_msgs.push(format!( + "use `self::{ident}` to refer to this {thing} unambiguously", + ident = ident, thing = b.descr(), + )) } if b.span.is_dummy() { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index d306e9ebe32..5db3efee9f6 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -42,7 +42,7 @@ use syntax_pos::{Span, DUMMY_SP}; use errors::Applicability; use std::cell::Cell; -use std::mem; +use std::{mem, ptr}; use rustc_data_structures::sync::Lrc; #[derive(Clone, Debug)] @@ -594,11 +594,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> { bitflags! { struct Flags: u8 { - const MACRO_RULES = 1 << 0; - const MODULE = 1 << 1; - const PRELUDE = 1 << 2; - const MISC_SUGGEST_SELF = 1 << 3; - const MISC_FROM_PRELUDE = 1 << 4; + const MACRO_RULES = 1 << 0; + const MODULE = 1 << 1; + const PRELUDE = 1 << 2; + const MISC_SUGGEST_CRATE = 1 << 3; + const MISC_SUGGEST_SELF = 1 << 4; + const MISC_FROM_PRELUDE = 1 << 5; } } @@ -684,7 +685,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { path_span, ); match binding { - Ok(binding) => Ok((binding, Flags::MODULE)), + Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)), Err((Determinacy::Undetermined, Weak::No)) => return Err(Determinacy::determined(force)), Err((Determinacy::Undetermined, Weak::Yes)) => @@ -706,7 +707,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> { self.current_module = orig_current_module; match binding { Ok(binding) => { - let misc_flags = if module.is_normal() { + let misc_flags = if ptr::eq(module, self.graph_root) { + Flags::MISC_SUGGEST_CRATE + } else if module.is_normal() { Flags::MISC_SUGGEST_SELF } else { Flags::empty() @@ -857,7 +860,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> { None }; if let Some(kind) = ambiguity_error_kind { - let misc = |f: Flags| if f.contains(Flags::MISC_SUGGEST_SELF) { + let misc = |f: Flags| if f.contains(Flags::MISC_SUGGEST_CRATE) { + AmbiguityErrorMisc::SuggestCrate + } else if f.contains(Flags::MISC_SUGGEST_SELF) { AmbiguityErrorMisc::SuggestSelf } else if f.contains(Flags::MISC_FROM_PRELUDE) { AmbiguityErrorMisc::FromPrelude @@ -866,7 +871,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { }; self.ambiguity_errors.push(AmbiguityError { kind, - ident, + ident: orig_ident, b1: innermost_binding, b2: binding, misc1: misc(innermost_flags), diff --git a/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr index ee98873064f..d288d729512 100644 --- a/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr +++ b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr @@ -14,7 +14,7 @@ note: `helper` could also refer to the attribute macro imported here | LL | use plugin::helper; | ^^^^^^^^^^^^^^ - = help: use `self::helper` to refer to this attribute macro unambiguously + = help: use `crate::helper` to refer to this attribute macro unambiguously error: aborting due to previous error diff --git a/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr b/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr index 34b21ea2683..79dc922b9db 100644 --- a/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr +++ b/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr @@ -16,7 +16,7 @@ note: `repr` could also refer to the attribute macro imported here | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ - = help: use `self::repr` to refer to this attribute macro unambiguously + = help: use `crate::repr` to refer to this attribute macro unambiguously error[E0659]: `repr` is ambiguous (built-in attribute vs any other name) --> $DIR/ambiguous-builtin-attrs.rs:11:19 @@ -30,7 +30,7 @@ note: `repr` could also refer to the attribute macro imported here | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ - = help: use `self::repr` to refer to this attribute macro unambiguously + = help: use `crate::repr` to refer to this attribute macro unambiguously error[E0659]: `repr` is ambiguous (built-in attribute vs any other name) --> $DIR/ambiguous-builtin-attrs.rs:20:34 @@ -44,7 +44,7 @@ note: `repr` could also refer to the attribute macro imported here | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ - = help: use `self::repr` to refer to this attribute macro unambiguously + = help: use `crate::repr` to refer to this attribute macro unambiguously error[E0659]: `repr` is ambiguous (built-in attribute vs any other name) --> $DIR/ambiguous-builtin-attrs.rs:22:11 @@ -58,7 +58,7 @@ note: `repr` could also refer to the attribute macro imported here | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ - = help: use `self::repr` to refer to this attribute macro unambiguously + = help: use `crate::repr` to refer to this attribute macro unambiguously error[E0659]: `feature` is ambiguous (built-in attribute vs any other name) --> $DIR/ambiguous-builtin-attrs.rs:3:4 @@ -72,7 +72,7 @@ note: `feature` could also refer to the attribute macro imported here | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ - = help: use `self::feature` to refer to this attribute macro unambiguously + = help: use `crate::feature` to refer to this attribute macro unambiguously error: aborting due to 6 previous errors diff --git a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr index f04782fac4d..cc50fefc464 100644 --- a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr +++ b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr @@ -14,7 +14,7 @@ note: `my_attr` could also refer to the attribute macro imported here | LL | use derive_helper_shadowing::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: use `self::my_attr` to refer to this attribute macro unambiguously + = help: use `crate::my_attr` to refer to this attribute macro unambiguously error: aborting due to previous error diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs index 562d3c9e70f..53ec3867f01 100644 --- a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs @@ -1,8 +1,6 @@ // edition:2018 // compile-flags:--extern edition_imports_2015 // aux-build:edition-imports-2015.rs -// error-pattern: `Ambiguous` is ambiguous -// error-pattern: `edition_imports_2015` is ambiguous mod edition_imports_2015 { pub struct Path; @@ -14,7 +12,8 @@ mod check { pub struct Ambiguous {} fn check() { - edition_imports_2015::gen_ambiguous!(); + edition_imports_2015::gen_ambiguous!(); //~ ERROR `Ambiguous` is ambiguous + //~| ERROR `edition_imports_2015` is ambiguous } } diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr index d0897d081c3..ac2bf21c5c0 100644 --- a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr @@ -1,36 +1,39 @@ error[E0659]: `Ambiguous` is ambiguous (name vs any other name during import resolution) - --> <::edition_imports_2015::gen_ambiguous macros>:1:15 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:15:9 | -LL | ( ) => { use Ambiguous ; type A = :: edition_imports_2015 :: Path ; } - | ^^^^^^^^^ ambiguous name +LL | edition_imports_2015::gen_ambiguous!(); //~ ERROR `Ambiguous` is ambiguous + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ambiguous name | note: `Ambiguous` could refer to the struct defined here - --> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:1 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:9:1 | LL | pub struct Ambiguous {} | ^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `crate::Ambiguous` to refer to this struct unambiguously note: `Ambiguous` could also refer to the struct defined here - --> $DIR/edition-imports-virtual-2015-ambiguity.rs:14:5 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:12:5 | LL | pub struct Ambiguous {} | ^^^^^^^^^^^^^^^^^^^^^^^ = help: use `self::Ambiguous` to refer to this struct unambiguously + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0659]: `edition_imports_2015` is ambiguous (name in the crate root vs extern crate during absolute path resolution) - --> <::edition_imports_2015::gen_ambiguous macros>:1:39 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:15:9 | -LL | ( ) => { use Ambiguous ; type A = :: edition_imports_2015 :: Path ; } - | ^^^^^^^^^^^^^^^^^^^^ ambiguous name +LL | edition_imports_2015::gen_ambiguous!(); //~ ERROR `Ambiguous` is ambiguous + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ambiguous name | = note: `edition_imports_2015` could refer to an extern crate passed with `--extern` - = help: use `::edition_imports_2015` to refer to this extern crate unambiguously note: `edition_imports_2015` could also refer to the module defined here - --> $DIR/edition-imports-virtual-2015-ambiguity.rs:7:1 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:5:1 | LL | / mod edition_imports_2015 { LL | | pub struct Path; LL | | } | |_^ + = help: use `crate::edition_imports_2015` to refer to this module unambiguously + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.rs b/src/test/ui/imports/local-modularized-tricky-fail-1.rs index fb05b95a96d..37633c7a441 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-1.rs +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.rs @@ -43,6 +43,7 @@ mod inner2 { fn main() { panic!(); //~ ERROR `panic` is ambiguous + //~| ERROR `panic` is ambiguous } mod inner3 { diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr index 962294e48ca..1978648e206 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr @@ -22,7 +22,7 @@ LL | use inner1::*; = help: consider adding an explicit import of `exported` to disambiguate error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/local-modularized-tricky-fail-1.rs:56:1 + --> $DIR/local-modularized-tricky-fail-1.rs:57:1 | LL | include!(); //~ ERROR `include` is ambiguous | ^^^^^^^ ambiguous name @@ -38,7 +38,7 @@ LL | | } ... LL | define_include!(); | ------------------ in this macro invocation - = help: use `self::include` to refer to this macro unambiguously + = help: use `crate::include` to refer to this macro unambiguously error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) --> $DIR/local-modularized-tricky-fail-1.rs:45:5 @@ -57,13 +57,13 @@ LL | | } ... LL | define_panic!(); | ---------------- in this macro invocation - = help: use `self::panic` to refer to this macro unambiguously + = help: use `crate::panic` to refer to this macro unambiguously error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> <::std::macros::panic macros>:1:13 + --> $DIR/local-modularized-tricky-fail-1.rs:45:5 | -LL | ( ) => ( { panic ! ( "explicit panic" ) } ) ; ( $ msg : expr ) => ( - | ^^^^^ ambiguous name +LL | panic!(); //~ ERROR `panic` is ambiguous + | ^^^^^^^^^ ambiguous name | = note: `panic` could refer to a macro from prelude note: `panic` could also refer to the macro defined here @@ -76,7 +76,8 @@ LL | | } ... LL | define_panic!(); | ---------------- in this macro invocation - = help: use `self::panic` to refer to this macro unambiguously + = help: use `crate::panic` to refer to this macro unambiguously + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/imports/macro-paths.stderr b/src/test/ui/imports/macro-paths.stderr index 8e8742f849b..3f481b0cfb0 100644 --- a/src/test/ui/imports/macro-paths.stderr +++ b/src/test/ui/imports/macro-paths.stderr @@ -34,7 +34,7 @@ LL | / pub mod baz { LL | | pub use two_macros::m; LL | | } | |_^ - = help: use `self::baz` to refer to this module unambiguously + = help: use `crate::baz` to refer to this module unambiguously error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/restricted-shadowing-legacy.stderr b/src/test/ui/macros/restricted-shadowing-legacy.stderr index 2135d63c80e..9d61799713b 100644 --- a/src/test/ui/macros/restricted-shadowing-legacy.stderr +++ b/src/test/ui/macros/restricted-shadowing-legacy.stderr @@ -3,6 +3,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -26,6 +29,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -49,6 +55,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -72,6 +81,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -95,6 +107,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -118,6 +133,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -141,6 +159,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -164,6 +185,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 diff --git a/src/test/ui/macros/restricted-shadowing-modern.stderr b/src/test/ui/macros/restricted-shadowing-modern.stderr index 2449e8512d3..398a7660d30 100644 --- a/src/test/ui/macros/restricted-shadowing-modern.stderr +++ b/src/test/ui/macros/restricted-shadowing-modern.stderr @@ -3,6 +3,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -26,6 +29,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -49,6 +55,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -72,6 +81,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -95,6 +107,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -118,6 +133,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr index ac8d3b9d0cb..a9e6da8f211 100644 --- a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr +++ b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr @@ -16,7 +16,7 @@ LL | | } ... LL | m!(); | ----- in this macro invocation - = help: use `self::std` to refer to this module unambiguously + = help: use `crate::std` to refer to this module unambiguously error: aborting due to previous error diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr b/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr index beeb74654e5..b1feb82fba9 100644 --- a/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr +++ b/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr @@ -13,7 +13,7 @@ LL | / mod std { LL | | pub struct io; LL | | } | |_^ - = help: use `self::std` to refer to this module unambiguously + = help: use `crate::std` to refer to this module unambiguously error: aborting due to previous error diff --git a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr index aa46947f93f..0088296b1a4 100644 --- a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr +++ b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr @@ -16,7 +16,7 @@ LL | / mod sub { LL | | pub fn bar() {} LL | | } | |_^ - = help: use `self::sub` to refer to this module unambiguously + = help: use `crate::sub` to refer to this module unambiguously error: aborting due to previous error diff --git a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr index 010b9efad39..213f723385b 100644 --- a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr +++ b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr @@ -14,7 +14,7 @@ note: `Foo` could also refer to the enum defined here | LL | enum Foo {} | ^^^^^^^^^^^ - = help: use `self::Foo` to refer to this enum unambiguously + = help: use `crate::Foo` to refer to this enum unambiguously error[E0659]: `std` is ambiguous (name vs any other name during import resolution) --> $DIR/block-scoped-shadow.rs:26:9 @@ -32,7 +32,7 @@ note: `std` could also refer to the struct defined here | LL | struct std; | ^^^^^^^^^^^ - = help: use `self::std` to refer to this struct unambiguously + = help: use `crate::std` to refer to this struct unambiguously error[E0659]: `std` is ambiguous (name vs any other name during import resolution) --> $DIR/block-scoped-shadow.rs:26:9 @@ -50,7 +50,7 @@ note: `std` could also refer to the unit struct defined here | LL | struct std; | ^^^^^^^^^^^ - = help: use `self::std` to refer to this unit struct unambiguously + = help: use `crate::std` to refer to this unit struct unambiguously error: aborting due to 3 previous errors From 6f028fe8e0db8c1251f24d694fc001aa933cf0ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 26 Nov 2018 13:58:46 -0800 Subject: [PATCH 0291/1984] Specify suggestion applicability --- src/libsyntax/parse/parser.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ab5afaf3d99..c224f182592 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5247,9 +5247,10 @@ impl<'a> Parser<'a> { "lifetime parameters must be declared prior to type parameters", ); if !suggestions.is_empty() { - err.multipart_suggestion( + err.multipart_suggestion_with_applicability( "move the lifetime parameter prior to the first type parameter", suggestions, + Applicability::MachineApplicable, ); } err.emit(); From 08140878fefaa4b16939b904bf825b7107069b42 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Tue, 23 Oct 2018 23:13:33 +0000 Subject: [PATCH 0292/1984] libcore: Add va_list lang item and intrinsics - Add the llvm intrinsics used to manipulate a va_list. - Add the va_list lang item in order to allow implementing VaList in libcore. --- src/libcore/ffi.rs | 185 +++++++++++++++++++++++++ src/librustc/middle/lang_items.rs | 1 + src/librustc_codegen_llvm/context.rs | 27 ++-- src/librustc_codegen_llvm/intrinsic.rs | 58 +++++++- src/librustc_codegen_llvm/lib.rs | 1 + src/librustc_codegen_llvm/va_arg.rs | 142 +++++++++++++++++++ src/librustc_typeck/check/intrinsic.rs | 52 +++++++ src/libstd/ffi/mod.rs | 7 + src/libstd/lib.rs | 1 + src/tools/tidy/src/pal.rs | 7 + 10 files changed, 468 insertions(+), 13 deletions(-) create mode 100644 src/librustc_codegen_llvm/va_arg.rs diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index a03756f9c22..edeb3b0d368 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -1,6 +1,7 @@ #![stable(feature = "", since = "1.30.0")] #![allow(non_camel_case_types)] +#![cfg_attr(stage0, allow(dead_code))] //! Utilities related to FFI bindings. @@ -40,3 +41,187 @@ impl fmt::Debug for c_void { f.pad("c_void") } } + +/// Basic implementation of a `va_list`. +#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), + not(target_arch = "x86_64")), + windows))] +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "27745")] +extern { + type VaListImpl; +} + +#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), + not(target_arch = "x86_64")), + windows))] +impl fmt::Debug for VaListImpl { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "va_list* {:p}", self) + } +} + +/// AArch64 ABI implementation of a `va_list`. See the +/// [Aarch64 Procedure Call Standard] for more details. +/// +/// [AArch64 Procedure Call Standard]: +/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf +#[cfg(all(target_arch = "aarch64", not(windows)))] +#[repr(C)] +#[derive(Debug)] +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "27745")] +struct VaListImpl { + stack: *mut (), + gr_top: *mut (), + vr_top: *mut (), + gr_offs: i32, + vr_offs: i32, +} + +/// PowerPC ABI implementation of a `va_list`. +#[cfg(all(target_arch = "powerpc", not(windows)))] +#[repr(C)] +#[derive(Debug)] +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "27745")] +struct VaListImpl { + gpr: u8, + fpr: u8, + reserved: u16, + overflow_arg_area: *mut (), + reg_save_area: *mut (), +} + +/// x86_64 ABI implementation of a `va_list`. +#[cfg(all(target_arch = "x86_64", not(windows)))] +#[repr(C)] +#[derive(Debug)] +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "27745")] +struct VaListImpl { + gp_offset: i32, + fp_offset: i32, + overflow_arg_area: *mut (), + reg_save_area: *mut (), +} + +/// A wrapper for a `va_list` +#[lang = "va_list"] +#[derive(Debug)] +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "27745")] +#[repr(transparent)] +#[cfg(not(stage0))] +pub struct VaList<'a>(&'a mut VaListImpl); + +// The VaArgSafe trait needs to be used in public interfaces, however, the trait +// itself must not be allowed to be used outside this module. Allowing users to +// implement the trait for a new type (thereby allowing the va_arg intrinsic to +// be used on a new type) is likely to cause undefined behavior. +// +// FIXME(dlrobertson): In order to use the VaArgSafe trait in a public interface +// but also ensure it cannot be used elsewhere, the trait needs to be public +// within a private module. Once RFC 2145 has been implemented look into +// improving this. +mod sealed_trait { + /// Trait which whitelists the allowed types to be used with [VaList::arg] + /// + /// [VaList::va_arg]: struct.VaList.html#method.arg + #[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "27745")] + pub trait VaArgSafe {} +} + +macro_rules! impl_va_arg_safe { + ($($t:ty),+) => { + $( + #[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "27745")] + impl sealed_trait::VaArgSafe for $t {} + )+ + } +} + +impl_va_arg_safe!{i8, i16, i32, i64, usize} +impl_va_arg_safe!{u8, u16, u32, u64, isize} +impl_va_arg_safe!{f64} + +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "27745")] +impl sealed_trait::VaArgSafe for *mut T {} +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "27745")] +impl sealed_trait::VaArgSafe for *const T {} + +#[cfg(not(stage0))] +impl<'a> VaList<'a> { + /// Advance to the next arg. + #[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "27745")] + pub unsafe fn arg(&mut self) -> T { + va_arg(self) + } + + /// Copy the `va_list` at the current location. + #[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "27745")] + pub unsafe fn copy(&mut self, f: F) -> R + where F: for<'copy> FnOnce(VaList<'copy>) -> R { + #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), + not(target_arch = "x86_64")), + windows))] + let mut ap = va_copy(self); + #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), + not(windows)))] + let mut ap_inner = va_copy(self); + #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), + not(windows)))] + let mut ap = VaList(&mut ap_inner); + let ret = f(VaList(ap.0)); + va_end(&mut ap); + ret + } +} + +#[cfg(not(stage0))] +extern "rust-intrinsic" { + /// Destroy the arglist `ap` after initialization with `va_start` or + /// `va_copy`. + fn va_end(ap: &mut VaList); + + /// Copy the current location of arglist `src` to the arglist `dst`. + #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), + not(target_arch = "x86_64")), + windows))] + fn va_copy<'a>(src: &VaList<'a>) -> VaList<'a>; + #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), + not(windows)))] + fn va_copy(src: &VaList) -> VaListImpl; + + /// Loads an argument of type `T` from the `va_list` `ap` and increment the + /// argument `ap` points to. + fn va_arg(ap: &mut VaList) -> T; +} diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 55ffa50e7c8..e7a8baf7383 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -297,6 +297,7 @@ language_item_table! { IndexMutTraitLangItem, "index_mut", index_mut_trait, Target::Trait; UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type, Target::Struct; + VaListTypeLangItem, "va_list", va_list, Target::Struct; DerefTraitLangItem, "deref", deref_trait, Target::Trait; DerefMutTraitLangItem, "deref_mut", deref_mut_trait, Target::Trait; diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 5b088ad2908..d954eb838cb 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -723,17 +723,17 @@ impl IntrinsicDeclarationMethods<'tcx> for CodegenCx<'b, 'tcx> { ifn!("llvm.bitreverse.i64", fn(t_i64) -> t_i64); ifn!("llvm.bitreverse.i128", fn(t_i128) -> t_i128); - ifn!("llvm.fshl.i8", fn(t_i8, t_i8, t_i8) -> t_i8); - ifn!("llvm.fshl.i16", fn(t_i16, t_i16, t_i16) -> t_i16); - ifn!("llvm.fshl.i32", fn(t_i32, t_i32, t_i32) -> t_i32); - ifn!("llvm.fshl.i64", fn(t_i64, t_i64, t_i64) -> t_i64); - ifn!("llvm.fshl.i128", fn(t_i128, t_i128, t_i128) -> t_i128); - - ifn!("llvm.fshr.i8", fn(t_i8, t_i8, t_i8) -> t_i8); - ifn!("llvm.fshr.i16", fn(t_i16, t_i16, t_i16) -> t_i16); - ifn!("llvm.fshr.i32", fn(t_i32, t_i32, t_i32) -> t_i32); - ifn!("llvm.fshr.i64", fn(t_i64, t_i64, t_i64) -> t_i64); - ifn!("llvm.fshr.i128", fn(t_i128, t_i128, t_i128) -> t_i128); + ifn!("llvm.fshl.i8", fn(t_i8, t_i8, t_i8) -> t_i8); + ifn!("llvm.fshl.i16", fn(t_i16, t_i16, t_i16) -> t_i16); + ifn!("llvm.fshl.i32", fn(t_i32, t_i32, t_i32) -> t_i32); + ifn!("llvm.fshl.i64", fn(t_i64, t_i64, t_i64) -> t_i64); + ifn!("llvm.fshl.i128", fn(t_i128, t_i128, t_i128) -> t_i128); + + ifn!("llvm.fshr.i8", fn(t_i8, t_i8, t_i8) -> t_i8); + ifn!("llvm.fshr.i16", fn(t_i16, t_i16, t_i16) -> t_i16); + ifn!("llvm.fshr.i32", fn(t_i32, t_i32, t_i32) -> t_i32); + ifn!("llvm.fshr.i64", fn(t_i64, t_i64, t_i64) -> t_i64); + ifn!("llvm.fshr.i128", fn(t_i128, t_i128, t_i128) -> t_i128); ifn!("llvm.sadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1}); ifn!("llvm.sadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1}); @@ -783,6 +783,11 @@ impl IntrinsicDeclarationMethods<'tcx> for CodegenCx<'b, 'tcx> { ifn!("llvm.assume", fn(i1) -> void); ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void); + // variadic intrinsics + ifn!("llvm.va_start", fn(i8p) -> void); + ifn!("llvm.va_end", fn(i8p) -> void); + ifn!("llvm.va_copy", fn(i8p, i8p) -> void); + if self.sess().opts.debuginfo != DebugInfo::None { ifn!("llvm.dbg.declare", fn(self.type_metadata(), self.type_metadata()) -> void); ifn!("llvm.dbg.value", fn(self.type_metadata(), t_i64, self.type_metadata()) -> void); diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 3548ccfd5a5..9c9b73f63fa 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -24,13 +24,14 @@ use context::CodegenCx; use type_::Type; use type_of::LayoutLlvmExt; use rustc::ty::{self, Ty}; -use rustc::ty::layout::{LayoutOf, HasTyCtxt}; +use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive}; use rustc_codegen_ssa::common::TypeKind; use rustc::hir; -use syntax::ast; +use syntax::ast::{self, FloatTy}; use syntax::symbol::Symbol; use builder::Builder; use value::Value; +use va_arg::emit_va_arg; use rustc_codegen_ssa::traits::*; @@ -146,6 +147,59 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let tp_ty = substs.type_at(0); self.cx().const_usize(self.cx().size_of(tp_ty).bytes()) } + func @ "va_start" | func @ "va_end" => { + let va_list = match (tcx.lang_items().va_list(), &result.layout.ty.sty) { + (Some(did), ty::Adt(def, _)) if def.did == did => args[0].immediate(), + (Some(_), _) => self.load(args[0].immediate(), + tcx.data_layout.pointer_align.abi), + (None, _) => bug!("va_list language item must be defined") + }; + let intrinsic = self.cx().get_intrinsic(&format!("llvm.{}", func)); + self.call(intrinsic, &[va_list], None) + } + "va_copy" => { + let va_list = match (tcx.lang_items().va_list(), &result.layout.ty.sty) { + (Some(did), ty::Adt(def, _)) if def.did == did => args[0].immediate(), + (Some(_), _) => self.load(args[0].immediate(), + tcx.data_layout.pointer_align.abi), + (None, _) => bug!("va_list language item must be defined") + }; + let intrinsic = self.cx().get_intrinsic(&("llvm.va_copy")); + self.call(intrinsic, &[llresult, va_list], None); + return; + } + "va_arg" => { + match fn_ty.ret.layout.abi { + layout::Abi::Scalar(ref scalar) => { + match scalar.value { + Primitive::Int(..) => { + if self.cx().size_of(ret_ty).bytes() < 4 { + // va_arg should not be called on a integer type + // less than 4 bytes in length. If it is, promote + // the integer to a `i32` and truncate the result + // back to the smaller type. + let promoted_result = emit_va_arg(self, args[0], + tcx.types.i32); + self.trunc(promoted_result, llret_ty) + } else { + emit_va_arg(self, args[0], ret_ty) + } + } + Primitive::Float(FloatTy::F64) | + Primitive::Pointer => { + emit_va_arg(self, args[0], ret_ty) + } + // `va_arg` should never be used with the return type f32. + Primitive::Float(FloatTy::F32) => { + bug!("the va_arg intrinsic does not work with `f32`") + } + } + } + _ => { + bug!("the va_arg intrinsic does not work with non-scalar types") + } + } + } "size_of_val" => { let tp_ty = substs.type_at(0); if let OperandValue::Pair(_, meta) = args[0].val { diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index f904a928d53..4f90cb793b6 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -127,6 +127,7 @@ mod mono_item; mod type_; mod type_of; mod value; +mod va_arg; #[derive(Clone)] pub struct LlvmCodegenBackend(()); diff --git a/src/librustc_codegen_llvm/va_arg.rs b/src/librustc_codegen_llvm/va_arg.rs new file mode 100644 index 00000000000..fbc3e6f06d1 --- /dev/null +++ b/src/librustc_codegen_llvm/va_arg.rs @@ -0,0 +1,142 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use builder::Builder; +use rustc_codegen_ssa::mir::operand::OperandRef; +use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods, ConstMethods, DerivedTypeMethods}; +use rustc::ty::layout::{Align, HasDataLayout, HasTyCtxt, LayoutOf, Size}; +use rustc::ty::Ty; +use type_::Type; +use type_of::LayoutLlvmExt; +use value::Value; + +#[allow(dead_code)] +fn round_pointer_up_to_alignment( + bx: &mut Builder<'a, 'll, 'tcx>, + addr: &'ll Value, + align: Align, + ptr_ty: &'ll Type +) -> &'ll Value { + let mut ptr_as_int = bx.ptrtoint(addr, bx.cx().type_isize()); + ptr_as_int = bx.add(ptr_as_int, bx.cx().const_i32(align.bytes() as i32 - 1)); + ptr_as_int = bx.and(ptr_as_int, bx.cx().const_i32(-(align.bytes() as i32))); + bx.inttoptr(ptr_as_int, ptr_ty) +} + +fn emit_direct_ptr_va_arg( + bx: &mut Builder<'a, 'll, 'tcx>, + list: OperandRef<'tcx, &'ll Value>, + llty: &'ll Type, + size: Size, + align: Align, + slot_size: Align, + allow_higher_align: bool +) -> (&'ll Value, Align) { + let va_list_ptr_ty = bx.cx().type_ptr_to(bx.cx.type_i8p()); + let va_list_addr = if list.layout.llvm_type(bx.cx) != va_list_ptr_ty { + bx.bitcast(list.immediate(), va_list_ptr_ty) + } else { + list.immediate() + }; + + let ptr = bx.load(va_list_addr, bx.tcx().data_layout.pointer_align.abi); + + let (addr, addr_align) = if allow_higher_align && align > slot_size { + (round_pointer_up_to_alignment(bx, ptr, align, bx.cx().type_i8p()), align) + } else { + (ptr, slot_size) + }; + + + let aligned_size = size.align_to(slot_size).bytes() as i32; + let full_direct_size = bx.cx().const_i32(aligned_size); + let next = bx.inbounds_gep(addr, &[full_direct_size]); + bx.store(next, va_list_addr, bx.tcx().data_layout.pointer_align.abi); + + if size.bytes() < slot_size.bytes() && + &*bx.tcx().sess.target.target.target_endian == "big" { + let adjusted_size = bx.cx().const_i32((slot_size.bytes() - size.bytes()) as i32); + let adjusted = bx.inbounds_gep(addr, &[adjusted_size]); + (bx.bitcast(adjusted, bx.cx().type_ptr_to(llty)), addr_align) + } else { + (bx.bitcast(addr, bx.cx().type_ptr_to(llty)), addr_align) + } +} + +fn emit_ptr_va_arg( + bx: &mut Builder<'a, 'll, 'tcx>, + list: OperandRef<'tcx, &'ll Value>, + target_ty: Ty<'tcx>, + indirect: bool, + slot_size: Align, + allow_higher_align: bool +) -> &'ll Value { + let layout = bx.cx.layout_of(target_ty); + let (llty, size, align) = if indirect { + (bx.cx.layout_of(bx.cx.tcx.mk_imm_ptr(target_ty)).llvm_type(bx.cx), + bx.cx.data_layout().pointer_size, + bx.cx.data_layout().pointer_align) + } else { + (layout.llvm_type(bx.cx), + layout.size, + layout.align) + }; + let (addr, addr_align) = emit_direct_ptr_va_arg(bx, list, llty, size, align.abi, + slot_size, allow_higher_align); + if indirect { + let tmp_ret = bx.load(addr, addr_align); + bx.load(tmp_ret, align.abi) + } else { + bx.load(addr, addr_align) + } +} + +pub(super) fn emit_va_arg( + bx: &mut Builder<'a, 'll, 'tcx>, + addr: OperandRef<'tcx, &'ll Value>, + target_ty: Ty<'tcx>, +) -> &'ll Value { + // Determine the va_arg implementation to use. The LLVM va_arg instruction + // is lacking in some instances, so we should only use it as a fallback. + let arch = &bx.cx.tcx.sess.target.target.arch; + match (&**arch, + bx.cx.tcx.sess.target.target.options.is_like_windows) { + ("x86", true) => { + emit_ptr_va_arg(bx, addr, target_ty, false, + Align::from_bytes(4).unwrap(), false) + } + ("x86_64", true) => { + let target_ty_size = bx.cx.size_of(target_ty).bytes(); + let indirect = if target_ty_size > 8 || !target_ty_size.is_power_of_two() { + true + } else { + false + }; + emit_ptr_va_arg(bx, addr, target_ty, indirect, + Align::from_bytes(8).unwrap(), false) + } + ("x86", false) => { + emit_ptr_va_arg(bx, addr, target_ty, false, + Align::from_bytes(4).unwrap(), true) + } + _ => { + let va_list = if (bx.tcx().sess.target.target.arch == "aarch64" || + bx.tcx().sess.target.target.arch == "x86_64" || + bx.tcx().sess.target.target.arch == "powerpc") && + !bx.tcx().sess.target.target.options.is_like_windows { + bx.load(addr.immediate(), bx.tcx().data_layout.pointer_align.abi) + } else { + addr.immediate() + }; + bx.va_arg(va_list, bx.cx.layout_of(target_ty).llvm_type(bx.cx)) + } + } +} + diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 9aad17626f9..2af21f54744 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -14,6 +14,7 @@ use intrinsics; use rustc::traits::{ObligationCause, ObligationCauseCode}; use rustc::ty::{self, TyCtxt, Ty}; +use rustc::ty::subst::Subst; use rustc::util::nodemap::FxHashMap; use require_same_types; @@ -81,6 +82,16 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::ForeignItem) { let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str()); let name = it.name.as_str(); + + let mk_va_list_ty = || { + tcx.lang_items().va_list().map(|did| { + let region = tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BrAnon(0))); + let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); + let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]); + tcx.mk_mut_ref(tcx.mk_region(env_region), va_list_ty) + }) + }; + let (n_tps, inputs, output, unsafety) = if name.starts_with("atomic_") { let split : Vec<&str> = name.split('_').collect(); assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format"); @@ -323,6 +334,47 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (0, vec![tcx.mk_fn_ptr(fn_ty), mut_u8, mut_u8], tcx.types.i32) } + "va_start" | "va_end" => { + match mk_va_list_ty() { + Some(va_list_ty) => (0, vec![va_list_ty], tcx.mk_unit()), + None => bug!("va_list lang_item must be defined to use va_list intrinsics") + } + } + + "va_copy" => { + match tcx.lang_items().va_list() { + Some(did) => { + let region = tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BrAnon(0))); + let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); + let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]); + let ret_ty = match va_list_ty.sty { + ty::Adt(def, _) if def.is_struct() => { + let fields = &def.non_enum_variant().fields; + match tcx.type_of(fields[0].did).subst(tcx, &[region.into()]).sty { + ty::Ref(_, element_ty, _) => match element_ty.sty { + ty::Adt(..) => element_ty, + _ => va_list_ty + } + _ => bug!("va_list structure is invalid") + } + } + _ => { + bug!("va_list structure is invalid") + } + }; + (0, vec![tcx.mk_imm_ref(tcx.mk_region(env_region), va_list_ty)], ret_ty) + } + None => bug!("va_list lang_item must be defined to use va_list intrinsics") + } + } + + "va_arg" => { + match mk_va_list_ty() { + Some(va_list_ty) => (1, vec![va_list_ty], param(0)), + None => bug!("va_list lang_item must be defined to use va_list intrinsics") + } + } + "nontemporal_store" => { (1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_unit()) } diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index a3345df5e0d..b438417fd4a 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -174,5 +174,12 @@ pub use self::os_str::{OsString, OsStr}; #[stable(feature = "raw_os", since = "1.1.0")] pub use core::ffi::c_void; +#[cfg(not(stage0))] +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "27745")] +pub use core::ffi::VaList; + mod c_str; mod os_str; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 575903d576a..5945ba6b090 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -244,6 +244,7 @@ #![feature(array_error_internals)] #![feature(asm)] #![feature(box_syntax)] +#![feature(c_variadic)] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] #![feature(cfg_target_vendor)] diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 12e9a54da52..822db253191 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -74,6 +74,13 @@ const EXCEPTION_PATHS: &[&str] = &[ "src/libcore/tests", "src/liballoc/tests/lib.rs", + // The `VaList` implementation must have platform specific code. + // The Windows implementation of a `va_list` is always a character + // pointer regardless of the target architecture. As a result, + // we must use `#[cfg(windows)]` to conditionally compile the + // correct `VaList` structure for windows. + "src/libcore/ffi.rs", + // non-std crates "src/test", "src/tools", From e9e084f5fa8820aca67e5cf0ec301e52bbae1028 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Tue, 23 Oct 2018 23:25:58 +0000 Subject: [PATCH 0293/1984] test: Add basic test for VaList --- .../c-link-to-rust-va-list-fn/Makefile | 6 + .../c-link-to-rust-va-list-fn/checkrust.rs | 142 ++++++++++++++++++ .../c-link-to-rust-va-list-fn/test.c | 95 ++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/Makefile create mode 100644 src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs create mode 100644 src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c diff --git a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/Makefile b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/Makefile new file mode 100644 index 00000000000..f124ca2ab61 --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + $(RUSTC) checkrust.rs + $(CC) test.c $(call STATICLIB,checkrust) $(call OUT_EXE,test) $(EXTRACFLAGS) + $(call RUN,test) diff --git a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs new file mode 100644 index 00000000000..d4cc4a0ed5e --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs @@ -0,0 +1,142 @@ +// Copyright 2018 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. + +#![crate_type = "staticlib"] +#![feature(c_variadic)] +#![feature(libc)] + +extern crate libc; + +use libc::{c_char, c_double, c_int, c_long, c_longlong}; +use std::ffi::VaList; +use std::slice; +use std::ffi::CStr; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum AnswerType { + Double, + Long, + LongLong, + Int, + Byte, + CStr, + Skip, +} + +#[repr(C)] +pub union AnswerData { + pub double: c_double, + pub long: c_long, + pub longlong: c_longlong, + pub int: c_int, + pub byte: c_char, + pub cstr: *const c_char, + pub skip_ty: AnswerType, +} + +#[repr(C)] +pub struct Answer { + tag: AnswerType, + data: AnswerData, +} + +#[no_mangle] +pub unsafe fn compare_answers(answers: &[Answer], mut ap: VaList) -> usize { + for (i, answer) in answers.iter().enumerate() { + match answer { + Answer { tag: AnswerType::Double, data: AnswerData { double: d } } => { + let tmp = ap.arg::(); + if d.floor() != tmp.floor() { + println!("Double: {} != {}", d, tmp); + return i + 1; + } + } + Answer { tag: AnswerType::Long, data: AnswerData { long: l } } => { + let tmp = ap.arg::(); + if *l != tmp { + println!("Long: {} != {}", l, tmp); + return i + 1; + } + } + Answer { tag: AnswerType::LongLong, data: AnswerData { longlong: l } } => { + let tmp = ap.arg::(); + if *l != tmp { + println!("Long Long: {} != {}", l, tmp); + return i + 1; + } + } + Answer { tag: AnswerType::Int, data: AnswerData { int: n } } => { + let tmp = ap.arg::(); + if *n != tmp { + println!("Int: {} != {}", n, tmp); + return i + 1; + } + } + Answer { tag: AnswerType::Byte, data: AnswerData { byte: b } } => { + let tmp = ap.arg::(); + if *b != tmp { + println!("Byte: {} != {}", b, tmp); + return i + 1; + } + } + Answer { tag: AnswerType::CStr, data: AnswerData { cstr: c0 } } => { + let c1 = ap.arg::<*const c_char>(); + let cstr0 = CStr::from_ptr(*c0); + let cstr1 = CStr::from_ptr(c1); + if cstr0 != cstr1 { + println!("C String: {:?} != {:?}", cstr0, cstr1); + return i + 1; + } + } + _ => { + println!("Unknown type!"); + return i + 1; + } + } + } + return 0; +} + +#[no_mangle] +pub unsafe extern "C" fn check_rust(argc: usize, answers: *const Answer, ap: VaList) -> usize { + let slice = slice::from_raw_parts(answers, argc); + compare_answers(slice, ap) +} + +#[no_mangle] +pub unsafe extern "C" fn check_rust_copy(argc: usize, answers: *const Answer, + mut ap: VaList) -> usize { + let slice = slice::from_raw_parts(answers, argc); + let mut skip_n = 0; + for (i, answer) in slice.iter().enumerate() { + match answer { + Answer { tag: AnswerType::Skip, data: AnswerData { skip_ty } } => { + match skip_ty { + AnswerType::Double => { ap.arg::(); } + AnswerType::Long => { ap.arg::(); } + AnswerType::LongLong => { ap.arg::(); } + AnswerType::Int => { ap.arg::(); } + AnswerType::Byte => { ap.arg::(); } + AnswerType::CStr => { ap.arg::<*const c_char>(); } + _ => { return i; } + }; + } + _ => { + skip_n = i; + break; + } + } + } + + ap.copy(|ap| { + compare_answers(&slice[skip_n..], ap) + }) +} diff --git a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c new file mode 100644 index 00000000000..80d9a480142 --- /dev/null +++ b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c @@ -0,0 +1,95 @@ +// Copyright 2018 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. + +#include +#include +#include +#include + +typedef enum { + TAG_DOUBLE, + TAG_LONG, + TAG_LONGLONG, + TAG_INT, + TAG_BYTE, + TAG_CSTR, + TAG_SKIP, +} tag; + +typedef struct { + tag answer_type; + union { + double double_precision; + long num_long; + long long num_longlong; + int num_int; + int8_t byte; + char* cstr; + tag skip_ty; + } answer_data; +} answer; + +#define MK_DOUBLE(n) \ + { TAG_DOUBLE, { .double_precision = n } } +#define MK_LONG(n) \ + { TAG_LONG, { .num_long = n } } +#define MK_LONGLONG(n) \ + { TAG_LONGLONG, { .num_longlong = n } } +#define MK_INT(n) \ + { TAG_INT, { .num_int = n } } +#define MK_BYTE(b) \ + { TAG_BYTE, { .byte = b } } +#define MK_CSTR(s) \ + { TAG_CSTR, { .cstr = s } } +#define MK_SKIP(ty) \ + { TAG_SKIP, { .skip_ty = TAG_ ## ty } } + +extern size_t check_rust(size_t argc, const answer* answers, va_list ap); +extern size_t check_rust_copy(size_t argc, const answer* answers, va_list ap); + +size_t test_check_rust(size_t argc, const answer* answers, ...) { + size_t ret = 0; + va_list ap; + va_start(ap, answers); + ret = check_rust(argc, answers, ap); + va_end(ap); + return ret; +} + +size_t test_check_rust_copy(size_t argc, const answer* answers, ...) { + size_t ret = 0; + va_list ap; + va_start(ap, answers); + ret = check_rust_copy(argc, answers, ap); + va_end(ap); + return ret; +} + +int main(int argc, char* argv[]) { + answer test_alignment0[] = {MK_LONGLONG(0x01LL), MK_INT(0x02), MK_LONGLONG(0x03LL)}; + assert(test_check_rust(3, test_alignment0, 0x01LL, 0x02, 0x03LL) == 0); + + answer test_alignment1[] = {MK_INT(-1), MK_BYTE('A'), MK_BYTE('4'), MK_BYTE(';'), + MK_INT(0x32), MK_INT(0x10000001), MK_CSTR("Valid!")}; + assert(test_check_rust(7, test_alignment1, -1, 'A', '4', ';', 0x32, 0x10000001, + "Valid!") == 0); + + answer basic_answers[] = {MK_DOUBLE(3.14), MK_LONG(12l), MK_BYTE('a'), + MK_DOUBLE(6.28), MK_CSTR("Hello"), MK_INT(42), + MK_CSTR("World")}; + assert(test_check_rust(7, basic_answers, 3.14, 12l, 'a', 6.28, "Hello", + 42, "World") == 0); + + answer copy_answers[] = { MK_SKIP(DOUBLE), MK_SKIP(INT), MK_SKIP(BYTE), MK_SKIP(CSTR), + MK_CSTR("Correctly skipped and copied list") }; + assert(test_check_rust_copy(5, copy_answers, 6.28, 16, 'A', "Skip Me!", + "Correctly skipped and copied list") == 0); + return 0; +} From 980cc6d2eeba8a79d25e6191323dd964c3cf88f0 Mon Sep 17 00:00:00 2001 From: Who? Me?! Date: Mon, 26 Nov 2018 21:28:28 -0600 Subject: [PATCH 0294/1984] rustc-guide has moved --- src/doc/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/index.md b/src/doc/index.md index f702052e049..33a9de1110b 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -107,6 +107,6 @@ Rust. It's also sometimes called "the 'nomicon." ## The `rustc` Contribution Guide -[The `rustc` Guide](https://rust-lang-nursery.github.io/rustc-guide/) documents how +[The `rustc` Guide](https://rust-lang.github.io/rustc-guide/) documents how the compiler works and how to contribute to it. This is useful if you want to build or modify the Rust compiler from source (e.g. to target something non-standard). From d4a6e739f3322c56e66fa8fef31569b7f16bc325 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Fri, 9 Nov 2018 15:12:09 +0100 Subject: [PATCH 0295/1984] Use sort_by_cached_key when key the function is not trivial/free --- src/librustc/middle/resolve_lifetime.rs | 2 +- src/librustc/traits/object_safety.rs | 2 +- src/librustc_mir/monomorphize/partitioning.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 6ff450508d1..07054ee99af 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -1573,7 +1573,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .collect(); // ensure that we issue lints in a repeatable order - def_ids.sort_by_key(|&def_id| self.tcx.def_path_hash(def_id)); + def_ids.sort_by_cached_key(|&def_id| self.tcx.def_path_hash(def_id)); for def_id in def_ids { debug!( diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index c79fa386123..2909daf22b3 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -409,7 +409,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { .collect::>(); // existential predicates need to be in a specific order - associated_types.sort_by_key(|item| self.def_path_hash(item.def_id)); + associated_types.sort_by_cached_key(|item| self.def_path_hash(item.def_id)); let projection_predicates = associated_types.into_iter().map(|item| { ty::ExistentialPredicate::Projection(ty::ExistentialProjection { diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 6dba020120f..3a6ee6da422 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -985,7 +985,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>( output.push_str(" @@"); let mut empty = Vec::new(); let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty); - cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone()); + cgus.as_mut_slice().sort_by_cached_key(|&(ref name, _)| name.clone()); cgus.dedup(); for &(ref cgu_name, (linkage, _)) in cgus.iter() { output.push_str(" "); From f2af41ab8c8a6519bd0175da9fcd873575810def Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Nov 2018 09:32:00 +0100 Subject: [PATCH 0296/1984] use MaybeUninit instead of mem::uninitialized for Windows Mutex --- src/libstd/sys/windows/mutex.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index b0e7331e2b6..3ba19a40d48 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -30,7 +30,7 @@ //! detect recursive locks. use cell::UnsafeCell; -use mem; +use mem::{self, MaybeUninit}; use sync::atomic::{AtomicUsize, Ordering}; use sys::c; use sys::compat; @@ -157,34 +157,34 @@ fn kind() -> Kind { return ret; } -pub struct ReentrantMutex { inner: UnsafeCell } +pub struct ReentrantMutex { inner: MaybeUninit> } unsafe impl Send for ReentrantMutex {} unsafe impl Sync for ReentrantMutex {} impl ReentrantMutex { - pub unsafe fn uninitialized() -> ReentrantMutex { - mem::uninitialized() + pub fn uninitialized() -> ReentrantMutex { + MaybeUninit::uninitialized() } pub unsafe fn init(&mut self) { - c::InitializeCriticalSection(self.inner.get()); + c::InitializeCriticalSection(self.inner.get_ref().get()); } pub unsafe fn lock(&self) { - c::EnterCriticalSection(self.inner.get()); + c::EnterCriticalSection(self.inner.get_ref().get()); } #[inline] pub unsafe fn try_lock(&self) -> bool { - c::TryEnterCriticalSection(self.inner.get()) != 0 + c::TryEnterCriticalSection(self.inner.get_ref().get()) != 0 } pub unsafe fn unlock(&self) { - c::LeaveCriticalSection(self.inner.get()); + c::LeaveCriticalSection(self.inner.get_ref().get()); } pub unsafe fn destroy(&self) { - c::DeleteCriticalSection(self.inner.get()); + c::DeleteCriticalSection(self.inner.get_ref().get()); } } From 6739c0e935ecfc838f818c27bfaa5665b6831e69 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 27 Nov 2018 09:59:44 +0100 Subject: [PATCH 0297/1984] Add missing doc link --- src/libcore/iter/iterator.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index fd4189ef50d..3063cb1a7df 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -519,7 +519,7 @@ pub trait Iterator { /// element. /// /// `map()` transforms one iterator into another, by means of its argument: - /// something that implements `FnMut`. It produces a new iterator which + /// something that implements [`FnMut`]. It produces a new iterator which /// calls this closure on each element of the original iterator. /// /// If you are good at thinking in types, you can think of `map()` like this: @@ -533,6 +533,7 @@ pub trait Iterator { /// more idiomatic to use [`for`] than `map()`. /// /// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for + /// [`FnMut`]: ../../std/ops/trait.FnMut.html /// /// # Examples /// From cd2e98dbd35f078fa14fbe021f1fb3861257e9a6 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 27 Nov 2018 03:26:37 +0300 Subject: [PATCH 0298/1984] resolve: Extern prelude is for type namespace only --- src/librustc_resolve/resolve_imports.rs | 4 +++- src/test/ui/imports/issue-56263.rs | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/imports/issue-56263.rs diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 3bfa862f0dc..e7cd32f4e81 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -173,7 +173,9 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { } ModuleOrUniformRoot::ExternPrelude => { assert!(!restricted_shadowing); - return if let Some(binding) = self.extern_prelude_get(ident, !record_used) { + return if ns != TypeNS { + Err((Determined, Weak::No)) + } else if let Some(binding) = self.extern_prelude_get(ident, !record_used) { Ok(binding) } else if !self.graph_root.unresolved_invocations.borrow().is_empty() { // Macro-expanded `extern crate` items can add names to extern prelude. diff --git a/src/test/ui/imports/issue-56263.rs b/src/test/ui/imports/issue-56263.rs new file mode 100644 index 00000000000..4113d4390c3 --- /dev/null +++ b/src/test/ui/imports/issue-56263.rs @@ -0,0 +1,8 @@ +// compile-pass +// edition:2018 + +use ::std; + +fn main() { + let std = 10; +} From a81027515069ac500dbbb6ea57bfb72a9eb948ac Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Nov 2018 13:48:40 +0100 Subject: [PATCH 0299/1984] fix build --- src/libstd/sys/windows/mutex.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 3ba19a40d48..a8eb82a8a66 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -164,7 +164,7 @@ unsafe impl Sync for ReentrantMutex {} impl ReentrantMutex { pub fn uninitialized() -> ReentrantMutex { - MaybeUninit::uninitialized() + ReentrantMutex { inner: MaybeUninit::uninitialized() } } pub unsafe fn init(&mut self) { From f460eac66e029a5165cac91e6bda0ee3af805b1e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 26 Nov 2018 08:27:36 +0100 Subject: [PATCH 0300/1984] use deterministic HashMap in libtest --- src/libtest/lib.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 7c26d042a7c..d59cc293c23 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1071,8 +1071,12 @@ pub fn run_tests(opts: &TestOpts, tests: Vec, mut callback: F) where F: FnMut(TestEvent) -> io::Result<()>, { - use std::collections::HashMap; + use std::collections::{self, HashMap}; + use std::hash::BuildHasherDefault; use std::sync::mpsc::RecvTimeoutError; + // Use a deterministic hasher + type TestMap = + HashMap>; let tests_len = tests.len(); @@ -1111,9 +1115,9 @@ where let (tx, rx) = channel::(); - let mut running_tests: HashMap = HashMap::new(); + let mut running_tests: TestMap = HashMap::default(); - fn get_timed_out_tests(running_tests: &mut HashMap) -> Vec { + fn get_timed_out_tests(running_tests: &mut TestMap) -> Vec { let now = Instant::now(); let timed_out = running_tests .iter() @@ -1131,7 +1135,7 @@ where timed_out }; - fn calc_timeout(running_tests: &HashMap) -> Option { + fn calc_timeout(running_tests: &TestMap) -> Option { running_tests.values().min().map(|next_timeout| { let now = Instant::now(); if *next_timeout >= now { From e9caa8ed91815d97a307d8708a441b0efa21712d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 26 Nov 2018 17:03:51 +0100 Subject: [PATCH 0301/1984] Do not spawn a thread if we do not use concurrency --- src/libtest/lib.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index d59cc293c23..ace314c081f 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1150,7 +1150,7 @@ where while !remaining.is_empty() { let test = remaining.pop().unwrap(); callback(TeWait(test.desc.clone()))?; - run_test(opts, !opts.run_tests, test, tx.clone()); + run_test(opts, !opts.run_tests, test, tx.clone(), /*concurrency*/false); let (test, result, stdout) = rx.recv().unwrap(); callback(TeResult(test, result, stdout))?; } @@ -1161,7 +1161,7 @@ where let timeout = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S); running_tests.insert(test.desc.clone(), timeout); callback(TeWait(test.desc.clone()))?; //here no pad - run_test(opts, !opts.run_tests, test, tx.clone()); + run_test(opts, !opts.run_tests, test, tx.clone(), /*concurrency*/true); pending += 1; } @@ -1193,7 +1193,7 @@ where // All benchmarks run at the end, in serial. for b in filtered_benchs { callback(TeWait(b.desc.clone()))?; - run_test(opts, false, b, tx.clone()); + run_test(opts, false, b, tx.clone(), /*concurrency*/true); let (test, result, stdout) = rx.recv().unwrap(); callback(TeResult(test, result, stdout))?; } @@ -1395,6 +1395,7 @@ pub fn run_test( force_ignore: bool, test: TestDescAndFn, monitor_ch: Sender, + concurrency: bool, ) { let TestDescAndFn { desc, testfn } = test; @@ -1411,6 +1412,7 @@ pub fn run_test( monitor_ch: Sender, nocapture: bool, testfn: Box, + concurrency: bool, ) { // Buffer for capturing standard I/O let data = Arc::new(Mutex::new(Vec::new())); @@ -1445,7 +1447,7 @@ pub fn run_test( // the test synchronously, regardless of the concurrency // level. let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_arch = "wasm32"); - if supports_threads { + if concurrency && supports_threads { let cfg = thread::Builder::new().name(name.as_slice().to_owned()); cfg.spawn(runtest).unwrap(); } else { @@ -1466,13 +1468,14 @@ pub fn run_test( } DynTestFn(f) => { let cb = move || __rust_begin_short_backtrace(f); - run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb)) + run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb), concurrency) } StaticTestFn(f) => run_test_inner( desc, monitor_ch, opts.nocapture, Box::new(move || __rust_begin_short_backtrace(f)), + concurrency, ), } } From 3e9cf3303ed29c9e511ff87d75e953d2118887bb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 26 Nov 2018 22:39:14 +0100 Subject: [PATCH 0302/1984] fix libtest test suite --- src/libtest/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index ace314c081f..cb249e1d5fc 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1798,7 +1798,7 @@ mod tests { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx); + run_test(&TestOpts::new(), false, desc, tx, /*concurrency*/false); let (_, res, _) = rx.recv().unwrap(); assert!(res != TrOk); } @@ -1816,7 +1816,7 @@ mod tests { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx); + run_test(&TestOpts::new(), false, desc, tx, /*concurrency*/false); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrIgnored); } @@ -1836,7 +1836,7 @@ mod tests { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx); + run_test(&TestOpts::new(), false, desc, tx, /*concurrency*/false); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrOk); } @@ -1856,7 +1856,7 @@ mod tests { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx); + run_test(&TestOpts::new(), false, desc, tx, /*concurrency*/false); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrOk); } @@ -1878,7 +1878,7 @@ mod tests { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx); + run_test(&TestOpts::new(), false, desc, tx, /*concurrency*/false); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrFailedMsg(format!("{} '{}'", failed_msg, expected))); } @@ -1896,7 +1896,7 @@ mod tests { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx); + run_test(&TestOpts::new(), false, desc, tx, /*concurrency*/false); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrFailed); } From 741ba1f2c29cf8f0f404699a284c4f3647d3d48a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Nov 2018 09:22:44 +0100 Subject: [PATCH 0303/1984] fix run-make-fulldeps/libtest-json --- src/test/run-make-fulldeps/libtest-json/output.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-make-fulldeps/libtest-json/output.json b/src/test/run-make-fulldeps/libtest-json/output.json index d8169ece89b..80e75c89bfc 100644 --- a/src/test/run-make-fulldeps/libtest-json/output.json +++ b/src/test/run-make-fulldeps/libtest-json/output.json @@ -2,7 +2,7 @@ { "type": "test", "event": "started", "name": "a" } { "type": "test", "name": "a", "event": "ok" } { "type": "test", "event": "started", "name": "b" } -{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'b' panicked at 'assertion failed: false', f.rs:18:5\nnote: Run with `RUST_BACKTRACE=1` for a backtrace.\n" } +{ "type": "test", "name": "b", "event": "failed", "stdout": "thread 'main' panicked at 'assertion failed: false', f.rs:18:5\nnote: Run with `RUST_BACKTRACE=1` for a backtrace.\n" } { "type": "test", "event": "started", "name": "c" } { "type": "test", "name": "c", "event": "ok" } { "type": "test", "event": "started", "name": "d" } From a8f9302047c97a07ecce3a85cdf222ff4da0d1e7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Nov 2018 13:57:53 +0100 Subject: [PATCH 0304/1984] avoid features_untracked --- src/librustc/ty/constness.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc/ty/constness.rs b/src/librustc/ty/constness.rs index 47aea7a5f07..e32913b8905 100644 --- a/src/librustc/ty/constness.rs +++ b/src/librustc/ty/constness.rs @@ -66,7 +66,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { } } else { // users enabling the `const_fn` feature gate can do what they want - !self.sess.features_untracked().const_fn + !self.features().const_fn } } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index fc2c6c3ab1f..09fe7b14c79 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -357,7 +357,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { TerminatorKind::FalseUnwind { .. } => None, TerminatorKind::Return => { - if !self.tcx.sess.features_untracked().const_let { + if !self.tcx.features().const_let { // Check for unused values. This usually means // there are extra statements in the AST. for temp in mir.temps_iter() { @@ -464,7 +464,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { LocalKind::ReturnPointer => { self.not_const(); } - LocalKind::Var if !self.tcx.sess.features_untracked().const_let => { + LocalKind::Var if !self.tcx.features().const_let => { if self.mode != Mode::Fn { emit_feature_err(&self.tcx.sess.parse_sess, "const_let", self.span, GateIssue::Language, @@ -558,7 +558,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { Mode::Fn => {}, _ => { if let ty::RawPtr(_) = base_ty.sty { - if !this.tcx.sess.features_untracked().const_raw_ptr_deref { + if !this.tcx.features().const_raw_ptr_deref { emit_feature_err( &this.tcx.sess.parse_sess, "const_raw_ptr_deref", this.span, GateIssue::Language, @@ -581,7 +581,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { match this.mode { Mode::Fn => this.not_const(), Mode::ConstFn => { - if !this.tcx.sess.features_untracked().const_fn_union { + if !this.tcx.features().const_fn_union { emit_feature_err( &this.tcx.sess.parse_sess, "const_fn_union", this.span, GateIssue::Language, @@ -807,7 +807,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { if let Mode::Fn = self.mode { // in normal functions, mark such casts as not promotable self.add(Qualif::NOT_CONST); - } else if !self.tcx.sess.features_untracked().const_raw_ptr_to_usize_cast { + } else if !self.tcx.features().const_raw_ptr_to_usize_cast { // in const fn and constants require the feature gate // FIXME: make it unsafe inside const fn and constants emit_feature_err( @@ -834,7 +834,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { if let Mode::Fn = self.mode { // raw pointer operations are not allowed inside promoteds self.add(Qualif::NOT_CONST); - } else if !self.tcx.sess.features_untracked().const_compare_raw_pointers { + } else if !self.tcx.features().const_compare_raw_pointers { // require the feature gate inside constants and const fn // FIXME: make it unsafe to use these operations emit_feature_err( @@ -933,7 +933,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { if self.mode != Mode::Fn { is_const_fn = true; // const eval transmute calls only with the feature gate - if !self.tcx.sess.features_untracked().const_transmute { + if !self.tcx.features().const_transmute { emit_feature_err( &self.tcx.sess.parse_sess, "const_transmute", self.span, GateIssue::Language, @@ -971,7 +971,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // FIXME: cannot allow this inside `allow_internal_unstable` because // that would make `panic!` insta stable in constants, since the // macro is marked with the attr - if self.tcx.sess.features_untracked().const_panic { + if self.tcx.features().const_panic { is_const_fn = true; } else { // don't allow panics in constants without the feature gate @@ -1158,7 +1158,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { if let (Mode::ConstFn, &Place::Local(index)) = (self.mode, dest) { if self.mir.local_kind(index) == LocalKind::Var && self.const_fn_arg_vars.insert(index) && - !self.tcx.sess.features_untracked().const_let { + !self.tcx.features().const_let { // Direct use of an argument is permitted. match *rvalue { From 9d35e57907ce2a57446e94dcf9e3403a51de6205 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Tue, 27 Nov 2018 23:37:59 +0900 Subject: [PATCH 0305/1984] Normalize type before deferred sizedness checking. --- src/librustc_typeck/check/mod.rs | 1 + src/test/run-pass/issue-56237.rs | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 src/test/run-pass/issue-56237.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e30a79b25de..44aa52651b0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -914,6 +914,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fcx.resolve_generator_interiors(def_id); for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) { + let ty = fcx.normalize_ty(span, ty); fcx.require_type_is_sized(ty, span, code); } fcx.select_all_obligations_or_error(); diff --git a/src/test/run-pass/issue-56237.rs b/src/test/run-pass/issue-56237.rs new file mode 100644 index 00000000000..87e10e83612 --- /dev/null +++ b/src/test/run-pass/issue-56237.rs @@ -0,0 +1,11 @@ +use std::ops::Deref; + +fn foo

(_value:

::Target) +where + P: Deref, +

::Target: Sized, +{} + +fn main() { + foo::>(2); +} From 2f2f37983d14c53c3328540d6cf44499c1699521 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Nov 2018 16:11:45 +0100 Subject: [PATCH 0306/1984] add missing feature --- src/libstd/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 575903d576a..8c8e7cb760e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -310,6 +310,7 @@ #![feature(panic_info_message)] #![feature(non_exhaustive)] #![feature(alloc_layout_extra)] +#![feature(maybe_uninit)] #![default_lib_allocator] From a4f12344c68530d1f42c5b00c10ab417137c0491 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Nov 2018 16:12:08 +0100 Subject: [PATCH 0307/1984] add comments explaining our uses of get_ref/get_mut for MaybeUninit --- src/libcore/fmt/float.rs | 3 +++ src/libcore/mem.rs | 6 ++++++ src/libstd/sys/windows/mutex.rs | 3 +++ 3 files changed, 12 insertions(+) diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index d01cd012031..0c1ac90dfd2 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -22,6 +22,9 @@ fn float_to_decimal_common_exact(fmt: &mut Formatter, num: &T, unsafe { let mut buf = MaybeUninit::<[u8; 1024]>::uninitialized(); // enough for f32 and f64 let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninitialized(); + // FIXME: Technically, this is calling `get_mut` on an uninitialized + // `MaybeUninit` (here and elsewhere in this file). Revisit this once + // we decided whether that is valid or not. let formatted = flt2dec::to_exact_fixed_str(flt2dec::strategy::grisu::format_exact, *num, sign, precision, false, buf.get_mut(), parts.get_mut()); diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index a5603ff6a62..626db7806df 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -1106,6 +1106,9 @@ impl MaybeUninit { /// /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized /// state, otherwise this will immediately cause undefined behavior. + // FIXME: We currently rely on the above being incorrect, i.e., we have references + // to uninitialized data (e.g. in `libstd/sys/windows/mutex.rs`). We should make + // a final decision about the rules before stabilization. #[unstable(feature = "maybe_uninit", issue = "53491")] #[inline(always)] pub unsafe fn get_ref(&self) -> &T { @@ -1118,6 +1121,9 @@ impl MaybeUninit { /// /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized /// state, otherwise this will immediately cause undefined behavior. + // FIXME: We currently rely on the above being incorrect, i.e., we have references + // to uninitialized data (e.g. in `libcore/fmt/float.rs`). We should make + // a final decision about the rules before stabilization. #[unstable(feature = "maybe_uninit", issue = "53491")] #[inline(always)] pub unsafe fn get_mut(&mut self) -> &mut T { diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index a8eb82a8a66..0c228f5097e 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -168,6 +168,9 @@ impl ReentrantMutex { } pub unsafe fn init(&mut self) { + // FIXME: Technically, this is calling `get_ref` on an uninitialized + // `MaybeUninit`. Revisit this once we decided whether that is valid + // or not. c::InitializeCriticalSection(self.inner.get_ref().get()); } From 7b429b0440eb7e8888ea600ca2103cb13999b3a2 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 27 Nov 2018 16:25:38 +0000 Subject: [PATCH 0308/1984] Fix stability attribute for ptr::hash --- src/libcore/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index c0e8e581144..13aae988d6c 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2526,7 +2526,7 @@ pub fn eq(a: *const T, b: *const T) -> bool { /// ptr::hash(five_ref, &mut hasher); /// println!("Hash is {:x}!", hasher.finish()); /// ``` -#[stable(feature = "rust1", since = "1.0.0")] // FIXME: replace with ??? +#[unstable(feature = "ptr_hash", reason = "newly added", issue = "56285")] pub fn hash(a: &T, into: &mut S) { use hash::Hash; NonNull::from(a).hash(into) From 81251491ddecb5c55b6d22b04abf33ef65d3a74b Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 27 Nov 2018 16:33:01 +0000 Subject: [PATCH 0309/1984] Pick a better variable name for ptr::hash --- 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 13aae988d6c..ff679d92e60 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2527,9 +2527,9 @@ pub fn eq(a: *const T, b: *const T) -> bool { /// println!("Hash is {:x}!", hasher.finish()); /// ``` #[unstable(feature = "ptr_hash", reason = "newly added", issue = "56285")] -pub fn hash(a: &T, into: &mut S) { +pub fn hash(hashee: &T, into: &mut S) { use hash::Hash; - NonNull::from(a).hash(into) + NonNull::from(hashee).hash(into) } // Impls for function pointers From afb4fbd951bc9780b5a7812f9a72aa9e2f085814 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 27 Nov 2018 16:46:24 +0000 Subject: [PATCH 0310/1984] Add an assert_eq in ptr::hash's doc example --- src/libcore/ptr.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index ff679d92e60..7b93795728b 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2524,7 +2524,13 @@ pub fn eq(a: *const T, b: *const T) -> bool { /// /// let mut hasher = DefaultHasher::new(); /// ptr::hash(five_ref, &mut hasher); -/// println!("Hash is {:x}!", hasher.finish()); +/// let actual = hasher.finish(); +/// +/// let mut hasher = DefaultHasher::new(); +/// (five_ref as *const T).hash(&mut hasher); +/// let expected = hasher.finish(); +/// +/// assert_eq!(actual, expected); /// ``` #[unstable(feature = "ptr_hash", reason = "newly added", issue = "56285")] pub fn hash(hashee: &T, into: &mut S) { From 4a7ffe2646b5d152297ab8008cc64693b4fd3d0a Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 27 Nov 2018 16:46:59 +0000 Subject: [PATCH 0311/1984] Fix issue number --- src/libcore/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 7b93795728b..7c8b195db8f 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2532,7 +2532,7 @@ pub fn eq(a: *const T, b: *const T) -> bool { /// /// assert_eq!(actual, expected); /// ``` -#[unstable(feature = "ptr_hash", reason = "newly added", issue = "56285")] +#[unstable(feature = "ptr_hash", reason = "newly added", issue = "56286")] pub fn hash(hashee: &T, into: &mut S) { use hash::Hash; NonNull::from(hashee).hash(into) From 73b656bbb306047d072b41321153b62c5a4a2b0d Mon Sep 17 00:00:00 2001 From: Marius Nuennerich Date: Tue, 27 Nov 2018 18:57:55 +0100 Subject: [PATCH 0312/1984] Fix small typo in comment --- src/libstd/thread/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 8a845efd413..3a9f3ec5c6f 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -326,7 +326,7 @@ impl Builder { /// Sets the size of the stack (in bytes) for the new thread. /// /// The actual stack size may be greater than this value if - /// the platform specifies minimal stack size. + /// the platform specifies a minimal stack size. /// /// For more information about the stack size for threads, see /// [this module-level documentation][stack-size]. From c75ed34732f67ce41faf84e22e4896cabab14a40 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sat, 24 Nov 2018 16:09:37 -0600 Subject: [PATCH 0313/1984] move feature gate to accepted --- src/libsyntax/feature_gate.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 73567765a04..cd503f25cfe 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -393,9 +393,6 @@ declare_features! ( // `extern` in paths (active, extern_in_paths, "1.23.0", Some(55600), None), - // Use `?` as the Kleene "at most one" operator - (active, macro_at_most_once_rep, "1.25.0", Some(48075), None), - // Infer static outlives requirements; RFC 2093 (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None), @@ -689,6 +686,8 @@ declare_features! ( (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), // Allows use of the :literal macro fragment specifier (RFC 1576) (accepted, macro_literal_matcher, "1.31.0", Some(35625), None), + // Use `?` as the Kleene "at most one" operator + (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), ); // If you change this, please modify src/doc/unstable-book as well. You must From a542e48871e040ea2db3b4fad5d88a83b6200855 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sat, 24 Nov 2018 16:12:16 -0600 Subject: [PATCH 0314/1984] remove feature gate --- src/libsyntax/ext/tt/quoted.rs | 46 ++++++---------------------------- src/libsyntax/feature_gate.rs | 3 --- 2 files changed, 7 insertions(+), 42 deletions(-) diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index 21848674831..c8ece7b3a88 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -576,22 +576,7 @@ where let span = match parse_kleene_op(input, span) { // #1 is a `?` (needs feature gate) Ok(Ok((op, op1_span))) if op == KleeneOp::ZeroOrOne => { - if !features.macro_at_most_once_rep - && !attr::contains_name(attrs, "allow_internal_unstable") - { - let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP; - emit_feature_err( - sess, - "macro_at_most_once_rep", - op1_span, - GateIssue::Language, - explain, - ); - - op1_span - } else { - return (None, op); - } + return (None, op); } // #1 is a `+` or `*` KleeneOp @@ -602,22 +587,10 @@ where // #2 is the `?` Kleene op, which does not take a separator (error) Ok(Ok((op, op2_span))) if op == KleeneOp::ZeroOrOne => { // Error! - - if !features.macro_at_most_once_rep - && !attr::contains_name(attrs, "allow_internal_unstable") - { - // FIXME: when `?` as a Kleene op is stabilized, we only need the "does not - // take a macro separator" error (i.e. the `else` case). - sess.span_diagnostic - .struct_span_err(op2_span, "expected `*` or `+`") - .note("`?` is not a macro repetition operator") - .emit(); - } else { - sess.span_diagnostic.span_err( - span, - "the `?` macro repetition operator does not take a separator", - ); - } + sess.span_diagnostic.span_err( + span, + "the `?` macro repetition operator does not take a separator", + ); // Return a dummy return (None, KleeneOp::ZeroOrMore); @@ -638,13 +611,8 @@ where }; // If we ever get to this point, we have experienced an "unexpected token" error - - if !features.macro_at_most_once_rep && !attr::contains_name(attrs, "allow_internal_unstable") { - sess.span_diagnostic.span_err(span, "expected `*` or `+`"); - } else { - sess.span_diagnostic - .span_err(span, "expected one of: `*`, `+`, or `?`"); - } + sess.span_diagnostic + .span_err(span, "expected one of: `*`, `+`, or `?`"); // Return a dummy (None, KleeneOp::ZeroOrMore) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index cd503f25cfe..3bc34917051 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1426,9 +1426,6 @@ pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str = pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = "unsized tuple coercion is not stable enough for use and is subject to change"; -pub const EXPLAIN_MACRO_AT_MOST_ONCE_REP: &'static str = - "using the `?` macro Kleene operator for \"at most one\" repetition is unstable"; - struct PostExpansionVisitor<'a> { context: &'a Context<'a>, } From 32aafb220313fbc91e8f55b12886d77d3e1cf24b Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sat, 24 Nov 2018 16:20:25 -0600 Subject: [PATCH 0315/1984] remove some unused vars --- src/libsyntax/ext/tt/quoted.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index c8ece7b3a88..edc431be369 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -11,13 +11,13 @@ use ast::NodeId; use early_buffered_lints::BufferedEarlyLintId; use ext::tt::macro_parser; -use feature_gate::{self, emit_feature_err, Features, GateIssue}; +use feature_gate::Features; use parse::{token, ParseSess}; use print::pprust; use symbol::keywords; use syntax_pos::{edition::Edition, BytePos, Span}; use tokenstream::{self, DelimSpan}; -use {ast, attr}; +use ast; use rustc_data_structures::sync::Lrc; use std::iter::Peekable; @@ -566,8 +566,8 @@ fn parse_sep_and_kleene_op_2018( input: &mut Peekable, span: Span, sess: &ParseSess, - features: &Features, - attrs: &[ast::Attribute], + _features: &Features, + _attrs: &[ast::Attribute], ) -> (Option, KleeneOp) where I: Iterator, @@ -575,7 +575,7 @@ where // We basically look at two token trees here, denoted as #1 and #2 below let span = match parse_kleene_op(input, span) { // #1 is a `?` (needs feature gate) - Ok(Ok((op, op1_span))) if op == KleeneOp::ZeroOrOne => { + Ok(Ok((op, _op1_span))) if op == KleeneOp::ZeroOrOne => { return (None, op); } @@ -585,7 +585,7 @@ where // #1 is a separator followed by #2, a KleeneOp Ok(Err((tok, span))) => match parse_kleene_op(input, span) { // #2 is the `?` Kleene op, which does not take a separator (error) - Ok(Ok((op, op2_span))) if op == KleeneOp::ZeroOrOne => { + Ok(Ok((op, _op2_span))) if op == KleeneOp::ZeroOrOne => { // Error! sess.span_diagnostic.span_err( span, From e97edad935c8eb05d0c67475e81dbb0618ac72fb Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sat, 24 Nov 2018 16:27:13 -0600 Subject: [PATCH 0316/1984] update tests --- ...ost-once-rep-2015-ques-rep-feature-flag.rs | 28 ------- ...once-rep-2015-ques-rep-feature-flag.stderr | 18 ----- ...acro-at-most-once-rep-2018-feature-gate.rs | 45 ----------- ...-at-most-once-rep-2018-feature-gate.stderr | 80 ------------------- .../ui/macros/macro-at-most-once-rep-2018.rs | 12 ++- .../macros/macro-at-most-once-rep-2018.stderr | 22 ++--- 6 files changed, 16 insertions(+), 189 deletions(-) delete mode 100644 src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs delete mode 100644 src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.stderr delete mode 100644 src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.rs delete mode 100644 src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.stderr diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs deleted file mode 100644 index 63a4ef16a25..00000000000 --- a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2012 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. - -// Test behavior of `?` macro _kleene op_ under the 2015 edition. Namely, it doesn't exist, even -// with the feature flag. - -// gate-test-macro_at_most_once_rep -// edition:2015 - -#![feature(macro_at_most_once_rep)] - -macro_rules! bar { - ($(a)?) => {} //~ERROR expected `*` or `+` -} - -macro_rules! baz { - ($(a),?) => {} //~ERROR expected `*` or `+` -} - -fn main() {} - diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.stderr b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.stderr deleted file mode 100644 index 5f687900421..00000000000 --- a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: expected `*` or `+` - --> $DIR/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs:20:10 - | -LL | ($(a)?) => {} //~ERROR expected `*` or `+` - | ^ - | - = note: `?` is not a macro repetition operator - -error: expected `*` or `+` - --> $DIR/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs:24:11 - | -LL | ($(a),?) => {} //~ERROR expected `*` or `+` - | ^ - | - = note: `?` is not a macro repetition operator - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.rs b/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.rs deleted file mode 100644 index ffabf9bcdf6..00000000000 --- a/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2012 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 gate test for macro_at_most_once_rep under 2018 edition. - -// gate-test-macro_at_most_once_rep -// edition:2018 - -macro_rules! foo { - ($(a)?) => {} - //~^ERROR using the `?` macro Kleene operator for - //~|ERROR expected `*` or `+` -} - -macro_rules! baz { - ($(a),?) => {} //~ERROR expected `*` or `+` -} - -macro_rules! barplus { - ($(a)?+) => {} - //~^ERROR using the `?` macro Kleene operator for - //~|ERROR expected `*` or `+` -} - -macro_rules! barstar { - ($(a)?*) => {} - //~^ERROR using the `?` macro Kleene operator for - //~|ERROR expected `*` or `+` -} - -pub fn main() { - foo!(); - foo!(a); - foo!(a?); //~ ERROR no rules expected the token `?` - foo!(a?a); //~ ERROR no rules expected the token `?` - foo!(a?a?a); //~ ERROR no rules expected the token `?` -} - diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.stderr b/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.stderr deleted file mode 100644 index 27dc03e1c39..00000000000 --- a/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.stderr +++ /dev/null @@ -1,80 +0,0 @@ -error[E0658]: using the `?` macro Kleene operator for "at most one" repetition is unstable (see issue #48075) - --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:17:10 - | -LL | ($(a)?) => {} - | ^ - | - = help: add #![feature(macro_at_most_once_rep)] to the crate attributes to enable - -error: expected `*` or `+` - --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:17:10 - | -LL | ($(a)?) => {} - | ^ - -error: expected `*` or `+` - --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:23:11 - | -LL | ($(a),?) => {} //~ERROR expected `*` or `+` - | ^ - | - = note: `?` is not a macro repetition operator - -error[E0658]: using the `?` macro Kleene operator for "at most one" repetition is unstable (see issue #48075) - --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:27:10 - | -LL | ($(a)?+) => {} - | ^ - | - = help: add #![feature(macro_at_most_once_rep)] to the crate attributes to enable - -error: expected `*` or `+` - --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:27:10 - | -LL | ($(a)?+) => {} - | ^ - -error[E0658]: using the `?` macro Kleene operator for "at most one" repetition is unstable (see issue #48075) - --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:33:10 - | -LL | ($(a)?*) => {} - | ^ - | - = help: add #![feature(macro_at_most_once_rep)] to the crate attributes to enable - -error: expected `*` or `+` - --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:33:10 - | -LL | ($(a)?*) => {} - | ^ - -error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:41:11 - | -LL | macro_rules! foo { - | ---------------- when calling this macro -... -LL | foo!(a?); //~ ERROR no rules expected the token `?` - | ^ no rules expected this token in macro call - -error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:42:11 - | -LL | macro_rules! foo { - | ---------------- when calling this macro -... -LL | foo!(a?a); //~ ERROR no rules expected the token `?` - | ^ no rules expected this token in macro call - -error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:43:11 - | -LL | macro_rules! foo { - | ---------------- when calling this macro -... -LL | foo!(a?a?a); //~ ERROR no rules expected the token `?` - | ^ no rules expected this token in macro call - -error: aborting due to 10 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.rs b/src/test/ui/macros/macro-at-most-once-rep-2018.rs index 5dabe8d9528..d8012c05acf 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2018.rs +++ b/src/test/ui/macros/macro-at-most-once-rep-2018.rs @@ -12,22 +12,20 @@ // edition:2018 -#![feature(macro_at_most_once_rep)] - macro_rules! foo { - ($(a)?) => {} + ($(a)?) => {}; } macro_rules! baz { - ($(a),?) => {} //~ERROR the `?` macro repetition operator + ($(a),?) => {}; //~ERROR the `?` macro repetition operator } macro_rules! barplus { - ($(a)?+) => {} // ok. matches "a+" and "+" + ($(a)?+) => {}; // ok. matches "a+" and "+" } macro_rules! barstar { - ($(a)?*) => {} // ok. matches "a*" and "*" + ($(a)?*) => {}; // ok. matches "a*" and "*" } pub fn main() { @@ -41,7 +39,7 @@ pub fn main() { barplus!(a); //~ERROR unexpected end of macro invocation barplus!(a?); //~ ERROR no rules expected the token `?` barplus!(a?a); //~ ERROR no rules expected the token `?` - barplus!(a+); + barplus!(a); barplus!(+); barstar!(); //~ERROR unexpected end of macro invocation diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr index d363b672680..efe0a2672c8 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr +++ b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr @@ -1,11 +1,11 @@ error: the `?` macro repetition operator does not take a separator - --> $DIR/macro-at-most-once-rep-2018.rs:22:10 + --> $DIR/macro-at-most-once-rep-2018.rs:20:10 | LL | ($(a),?) => {} //~ERROR the `?` macro repetition operator | ^ error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018.rs:36:11 + --> $DIR/macro-at-most-once-rep-2018.rs:34:11 | LL | macro_rules! foo { | ---------------- when calling this macro @@ -14,7 +14,7 @@ LL | foo!(a?); //~ ERROR no rules expected the token `?` | ^ no rules expected this token in macro call error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018.rs:37:11 + --> $DIR/macro-at-most-once-rep-2018.rs:35:11 | LL | macro_rules! foo { | ---------------- when calling this macro @@ -23,7 +23,7 @@ LL | foo!(a?a); //~ ERROR no rules expected the token `?` | ^ no rules expected this token in macro call error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018.rs:38:11 + --> $DIR/macro-at-most-once-rep-2018.rs:36:11 | LL | macro_rules! foo { | ---------------- when calling this macro @@ -32,7 +32,7 @@ LL | foo!(a?a?a); //~ ERROR no rules expected the token `?` | ^ no rules expected this token in macro call error: unexpected end of macro invocation - --> $DIR/macro-at-most-once-rep-2018.rs:40:5 + --> $DIR/macro-at-most-once-rep-2018.rs:38:5 | LL | macro_rules! barplus { | -------------------- when calling this macro @@ -50,7 +50,7 @@ LL | barplus!(a); //~ERROR unexpected end of macro invocation | ^ missing tokens in macro arguments error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018.rs:42:15 + --> $DIR/macro-at-most-once-rep-2018.rs:40:15 | LL | macro_rules! barplus { | -------------------- when calling this macro @@ -59,7 +59,7 @@ LL | barplus!(a?); //~ ERROR no rules expected the token `?` | ^ no rules expected this token in macro call error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018.rs:43:15 + --> $DIR/macro-at-most-once-rep-2018.rs:41:15 | LL | macro_rules! barplus { | -------------------- when calling this macro @@ -68,7 +68,7 @@ LL | barplus!(a?a); //~ ERROR no rules expected the token `?` | ^ no rules expected this token in macro call error: unexpected end of macro invocation - --> $DIR/macro-at-most-once-rep-2018.rs:47:5 + --> $DIR/macro-at-most-once-rep-2018.rs:45:5 | LL | macro_rules! barstar { | -------------------- when calling this macro @@ -77,7 +77,7 @@ LL | barstar!(); //~ERROR unexpected end of macro invocation | ^^^^^^^^^^^ missing tokens in macro arguments error: unexpected end of macro invocation - --> $DIR/macro-at-most-once-rep-2018.rs:48:15 + --> $DIR/macro-at-most-once-rep-2018.rs:46:14 | LL | macro_rules! barstar { | -------------------- when calling this macro @@ -86,7 +86,7 @@ LL | barstar!(a); //~ERROR unexpected end of macro invocation | ^ missing tokens in macro arguments error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018.rs:49:15 + --> $DIR/macro-at-most-once-rep-2018.rs:47:15 | LL | macro_rules! barstar { | -------------------- when calling this macro @@ -95,7 +95,7 @@ LL | barstar!(a?); //~ ERROR no rules expected the token `?` | ^ no rules expected this token in macro call error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018.rs:50:15 + --> $DIR/macro-at-most-once-rep-2018.rs:48:15 | LL | macro_rules! barstar { | -------------------- when calling this macro From f3b29ca1c21b1cd559441a57e1ff2b8a41d56e36 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sat, 24 Nov 2018 16:29:43 -0600 Subject: [PATCH 0317/1984] remove unstable book entry --- .../macro-at-most-once-rep.md | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/macro-at-most-once-rep.md diff --git a/src/doc/unstable-book/src/language-features/macro-at-most-once-rep.md b/src/doc/unstable-book/src/language-features/macro-at-most-once-rep.md deleted file mode 100644 index 251fc720912..00000000000 --- a/src/doc/unstable-book/src/language-features/macro-at-most-once-rep.md +++ /dev/null @@ -1,22 +0,0 @@ -# `macro_at_most_once_rep` - -NOTE: This feature is only available in the 2018 Edition. - -The tracking issue for this feature is: #48075 - -With this feature gate enabled, one can use `?` as a Kleene operator meaning "0 -or 1 repetitions" in a macro definition. Previously only `+` and `*` were allowed. - -For example: - -```rust,ignore -#![feature(macro_at_most_once_rep)] - -macro_rules! foo { - (something $(,)?) // `?` indicates `,` is "optional"... - => {} -} -``` - ------------------------- - From 59ae93daed93024a3dd413132451f246863f6f97 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sat, 24 Nov 2018 17:26:15 -0600 Subject: [PATCH 0318/1984] remove uses of feature gate --- src/doc/unstable-book/src/language-features/plugin.md | 1 - src/libcore/lib.rs | 1 - src/librustc/lib.rs | 1 - src/librustc_lint/lib.rs | 1 - src/librustc_metadata/lib.rs | 1 - src/libsyntax/lib.rs | 1 - src/test/compile-fail-fulldeps/auxiliary/lint_for_crate.rs | 1 - .../compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs | 1 - src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs | 1 - src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs | 1 - .../proc-macro/auxiliary/issue-40001-plugin.rs | 1 - src/test/run-pass/macros/macro-at-most-once-rep.rs | 2 -- src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs | 1 - src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs | 1 - src/test/ui-fulldeps/auxiliary/lint_tool_test.rs | 1 - 15 files changed, 16 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index 74bdd4dc3b5..03ea392c863 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -181,7 +181,6 @@ that warns about any item named `lintme`. ```rust,ignore #![feature(plugin_registrar)] #![feature(box_syntax, rustc_private)] -#![feature(macro_at_most_once_rep)] extern crate syntax; diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a02b5bc87c5..726e891df0c 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -93,7 +93,6 @@ #![feature(never_type)] #![feature(nll)] #![feature(exhaustive_patterns)] -#![feature(macro_at_most_once_rep)] #![feature(no_core)] #![feature(on_unimplemented)] #![feature(optin_builtin_traits)] diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 0aa964a44fd..9ae59242fbf 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -67,7 +67,6 @@ #![feature(integer_atomics)] #![feature(test)] #![feature(in_band_lifetimes)] -#![feature(macro_at_most_once_rep)] #![feature(crate_visibility_modifier)] #![feature(transpose_result)] diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 57cbecb5c67..71efc5654ef 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -29,7 +29,6 @@ #![feature(nll)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] -#![feature(macro_at_most_once_rep)] #[macro_use] extern crate syntax; diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 0322c888ad5..ee99f7465b9 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -14,7 +14,6 @@ #![feature(box_patterns)] #![feature(libc)] -#![feature(macro_at_most_once_rep)] #![feature(nll)] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 9bbd59e09be..ca9c5ad7b60 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -20,7 +20,6 @@ test(attr(deny(warnings))))] #![feature(crate_visibility_modifier)] -#![feature(macro_at_most_once_rep)] #![feature(nll)] #![feature(rustc_attrs)] #![feature(rustc_diagnostic_macros)] diff --git a/src/test/compile-fail-fulldeps/auxiliary/lint_for_crate.rs b/src/test/compile-fail-fulldeps/auxiliary/lint_for_crate.rs index 460e28fc794..fc53031e7f2 100644 --- a/src/test/compile-fail-fulldeps/auxiliary/lint_for_crate.rs +++ b/src/test/compile-fail-fulldeps/auxiliary/lint_for_crate.rs @@ -12,7 +12,6 @@ #![feature(plugin_registrar, rustc_private)] #![feature(box_syntax)] -#![feature(macro_at_most_once_rep)] #[macro_use] extern crate rustc; extern crate rustc_plugin; diff --git a/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs b/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs index 1057649d969..f697642f843 100644 --- a/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs +++ b/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs @@ -12,7 +12,6 @@ #![feature(plugin_registrar)] #![feature(box_syntax, rustc_private)] -#![feature(macro_at_most_once_rep)] // Load rustc as a plugin to get macros #[macro_use] diff --git a/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs b/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs index b0183a3c56b..8647797270f 100644 --- a/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs +++ b/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs @@ -12,7 +12,6 @@ #![feature(plugin_registrar)] #![feature(box_syntax, rustc_private)] -#![feature(macro_at_most_once_rep)] extern crate syntax; diff --git a/src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs b/src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs index 00c419a8d09..9f6927d2164 100644 --- a/src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs +++ b/src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs @@ -12,7 +12,6 @@ #![feature(plugin_registrar, rustc_private)] #![feature(box_syntax)] -#![feature(macro_at_most_once_rep)] #[macro_use] extern crate rustc; extern crate rustc_plugin; diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs index e0acf340a79..f4d3f2c94ca 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs @@ -9,7 +9,6 @@ // except according to those terms. #![feature(box_syntax, plugin, plugin_registrar, rustc_private)] -#![feature(macro_at_most_once_rep)] #![crate_type = "dylib"] #[macro_use] diff --git a/src/test/run-pass/macros/macro-at-most-once-rep.rs b/src/test/run-pass/macros/macro-at-most-once-rep.rs index c7129423cb6..563fd01c111 100644 --- a/src/test/run-pass/macros/macro-at-most-once-rep.rs +++ b/src/test/run-pass/macros/macro-at-most-once-rep.rs @@ -22,8 +22,6 @@ // edition:2018 -#![feature(macro_at_most_once_rep)] - macro_rules! foo { ($($a:ident)? ; $num:expr) => { { let mut x = 0; diff --git a/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs b/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs index 1057649d969..f697642f843 100644 --- a/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs @@ -12,7 +12,6 @@ #![feature(plugin_registrar)] #![feature(box_syntax, rustc_private)] -#![feature(macro_at_most_once_rep)] // Load rustc as a plugin to get macros #[macro_use] diff --git a/src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs b/src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs index b0183a3c56b..8647797270f 100644 --- a/src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs @@ -12,7 +12,6 @@ #![feature(plugin_registrar)] #![feature(box_syntax, rustc_private)] -#![feature(macro_at_most_once_rep)] extern crate syntax; diff --git a/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs b/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs index 7d2acd7aa4c..0a449e338bd 100644 --- a/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs @@ -10,7 +10,6 @@ #![feature(plugin_registrar)] #![feature(box_syntax, rustc_private)] -#![feature(macro_at_most_once_rep)] extern crate syntax; From aeede9eb468f373f2c3250899606b0a68e8b8a18 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sat, 24 Nov 2018 18:40:03 -0600 Subject: [PATCH 0319/1984] fix test --- src/test/ui/macros/macro-at-most-once-rep-2018.rs | 2 +- src/test/ui/macros/macro-at-most-once-rep-2018.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.rs b/src/test/ui/macros/macro-at-most-once-rep-2018.rs index d8012c05acf..78bdf8ff71b 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2018.rs +++ b/src/test/ui/macros/macro-at-most-once-rep-2018.rs @@ -39,7 +39,7 @@ pub fn main() { barplus!(a); //~ERROR unexpected end of macro invocation barplus!(a?); //~ ERROR no rules expected the token `?` barplus!(a?a); //~ ERROR no rules expected the token `?` - barplus!(a); + barplus!(a+); barplus!(+); barstar!(); //~ERROR unexpected end of macro invocation diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr index efe0a2672c8..43779078ebc 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr +++ b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr @@ -1,7 +1,7 @@ error: the `?` macro repetition operator does not take a separator --> $DIR/macro-at-most-once-rep-2018.rs:20:10 | -LL | ($(a),?) => {} //~ERROR the `?` macro repetition operator +LL | ($(a),?) => {}; //~ERROR the `?` macro repetition operator | ^ error: no rules expected the token `?` From 999595f640b0f64c682ee78dfa82b6a43d979ec2 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 27 Nov 2018 13:06:49 -0700 Subject: [PATCH 0320/1984] Re-enable lldb Commit 7215963e56 disabled lldb due to the LLVM update. This patch updates lldb to build against the Rust LLVM, and re-enables it. --- .gitmodules | 4 ++-- .travis.yml | 6 +++--- src/tools/clang | 2 +- src/tools/lldb | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitmodules b/.gitmodules index bf9bdd9a5b4..304bdeff429 100644 --- a/.gitmodules +++ b/.gitmodules @@ -56,9 +56,9 @@ [submodule "src/tools/lldb"] path = src/tools/lldb url = https://github.com/rust-lang-nursery/lldb.git - branch = rust-release-80-v1 + branch = rust-release-80-v2 [submodule "src/tools/clang"] path = src/tools/clang url = https://github.com/rust-lang-nursery/clang.git - branch = rust-release-80-v1 + branch = rust-release-80-v2 diff --git a/.travis.yml b/.travis.yml index fa66220f442..14fb17aeedd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ matrix: - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler --set rust.jemalloc" + RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler --enable-lldb --set rust.jemalloc" SRC=. DEPLOY_ALT=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 @@ -87,7 +87,7 @@ matrix: # OSX 10.7 and `xcode7` is the latest Xcode able to compile LLVM for 10.7. - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler --set rust.jemalloc" + RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc" SRC=. DEPLOY=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 @@ -102,7 +102,7 @@ matrix: - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc" + RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --enable-lldb --set rust.jemalloc" SRC=. DEPLOY=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 diff --git a/src/tools/clang b/src/tools/clang index d0fc1788123..032312dd014 160000 --- a/src/tools/clang +++ b/src/tools/clang @@ -1 +1 @@ -Subproject commit d0fc1788123de9844c8088b977cd142021cea1f2 +Subproject commit 032312dd0140a7074c9b89d305fe44eb0e44e407 diff --git a/src/tools/lldb b/src/tools/lldb index fdea743be55..8ad0817ce45 160000 --- a/src/tools/lldb +++ b/src/tools/lldb @@ -1 +1 @@ -Subproject commit fdea743be550ed8d7b61b2c908944cdd1290a6ad +Subproject commit 8ad0817ce45b0eef9d374691b23f2bd69c164254 From 9755410f73584909ffa2f3241a946d47139d1902 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 27 Nov 2018 20:09:18 +0000 Subject: [PATCH 0321/1984] Try to fix ptr::hash's doc example --- src/libcore/ptr.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 7c8b195db8f..3024031b3bb 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2516,18 +2516,19 @@ pub fn eq(a: *const T, b: *const T) -> bool { /// /// ``` /// use std::collections::hash_map::DefaultHasher; -/// use std::hash::Hasher; +/// use std::hash::{Hash, Hasher}; /// use std::ptr; /// /// let five = 5; /// let five_ref = &five; /// /// let mut hasher = DefaultHasher::new(); +/// #[feature(ptr_hash)] /// ptr::hash(five_ref, &mut hasher); /// let actual = hasher.finish(); /// /// let mut hasher = DefaultHasher::new(); -/// (five_ref as *const T).hash(&mut hasher); +/// (five_ref as *const i32).hash(&mut hasher); /// let expected = hasher.finish(); /// /// assert_eq!(actual, expected); From 2dd48f834f4b80f2a3f2103b01b638c46eb44d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Tue, 27 Nov 2018 21:21:57 +0100 Subject: [PATCH 0322/1984] submodules: update clippy from 754b4c07 to b2601beb Changes: ```` Fix NAIVE_BYTECOUNT applicability Fix dogfood error Change Applicability of MISTYPED_LITERAL_SUFFIX Add applicability level to (nearly) every span_lint_and_sugg function Update stderr file Fix bugs and improve documentation Add Applicability::Unspecified to span_lint_and_sugg functions Introduce snippet_with_applicability and hir_with_applicability functions readme: tell how to install clippy on travis from git if it is not shipped with a nightly. constants: add u128 i128 builtin types and fix outdated url Update lints Lint only the first statment/expression after alloc Fix some warnings related to Self Rename some symbols Split lint into slow and unsafe vector initalization Add unsafe set_len initialization Add slow zero-filled vector initialization lint Travis: Remove `sudo: false` Downgrade needless_pass_by_value to allow by default ```` --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index 754b4c07233..b2601beb35b 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 754b4c07233ee18820265bd18467aa82263f9a3a +Subproject commit b2601beb35b56fd33bd387a1faeccd3ae02352ed From 097b5db5f67c28719d0065c6a74a2e56ae52d2d3 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 27 Nov 2018 21:18:20 +0000 Subject: [PATCH 0323/1984] Move feature enable in ptr::hash doc example --- src/libcore/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 3024031b3bb..0213b310efa 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2515,6 +2515,7 @@ pub fn eq(a: *const T, b: *const T) -> bool { /// # Examples /// /// ``` +/// #![feature(ptr_hash)] /// use std::collections::hash_map::DefaultHasher; /// use std::hash::{Hash, Hasher}; /// use std::ptr; @@ -2523,7 +2524,6 @@ pub fn eq(a: *const T, b: *const T) -> bool { /// let five_ref = &five; /// /// let mut hasher = DefaultHasher::new(); -/// #[feature(ptr_hash)] /// ptr::hash(five_ref, &mut hasher); /// let actual = hasher.finish(); /// From e63bd91895e640a5736ef37eb1d0dedc11fe3138 Mon Sep 17 00:00:00 2001 From: polyfloyd Date: Tue, 27 Nov 2018 22:33:46 +0100 Subject: [PATCH 0324/1984] Fix a typo in the documentation of std::ffi --- src/libstd/ffi/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index a3345df5e0d..f1f3742996b 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -112,12 +112,12 @@ //! ## On Unix //! //! On Unix, [`OsStr`] implements the -//! `std::os::unix:ffi::`[`OsStrExt`][unix.OsStrExt] trait, which +//! `std::os::unix::ffi::`[`OsStrExt`][unix.OsStrExt] trait, which //! augments it with two methods, [`from_bytes`] and [`as_bytes`]. //! These do inexpensive conversions from and to UTF-8 byte slices. //! //! Additionally, on Unix [`OsString`] implements the -//! `std::os::unix:ffi::`[`OsStringExt`][unix.OsStringExt] trait, +//! `std::os::unix::ffi::`[`OsStringExt`][unix.OsStringExt] trait, //! which provides [`from_vec`] and [`into_vec`] methods that consume //! their arguments, and take or produce vectors of [`u8`]. //! From d8190afbcb9b15eb8e04d3860a5bd018568a3980 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 28 Nov 2018 00:25:40 +0100 Subject: [PATCH 0325/1984] Fix alignment of stores to scalar pair The alignment for the second element of a scalar pair is not the same as for the first element. Make sure it is computed correctly based on the element size. --- src/librustc_codegen_ssa/mir/operand.rs | 20 +++++++++++++++----- src/test/codegen/issue-56267.rs | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 src/test/codegen/issue-56267.rs diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 92d0219caf0..fefbc14e497 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -331,11 +331,21 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandValue { bx.store_with_flags(val, dest.llval, dest.align, flags); } OperandValue::Pair(a, b) => { - for (i, &x) in [a, b].iter().enumerate() { - let llptr = bx.struct_gep(dest.llval, i as u64); - let val = base::from_immediate(bx, x); - bx.store_with_flags(val, llptr, dest.align, flags); - } + let (a_scalar, b_scalar) = match dest.layout.abi { + layout::Abi::ScalarPair(ref a, ref b) => (a, b), + _ => bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout) + }; + let b_offset = a_scalar.value.size(bx).align_to(b_scalar.value.align(bx).abi); + + let llptr = bx.struct_gep(dest.llval, 0); + let val = base::from_immediate(bx, a); + let align = dest.align; + bx.store_with_flags(val, llptr, align, flags); + + let llptr = bx.struct_gep(dest.llval, 1); + let val = base::from_immediate(bx, b); + let align = dest.align.restrict_for_offset(b_offset); + bx.store_with_flags(val, llptr, align, flags); } } } diff --git a/src/test/codegen/issue-56267.rs b/src/test/codegen/issue-56267.rs new file mode 100644 index 00000000000..2c33f558931 --- /dev/null +++ b/src/test/codegen/issue-56267.rs @@ -0,0 +1,18 @@ +// compile-flags: -C no-prepopulate-passes + +#![crate_type="rlib"] + +#[allow(dead_code)] +pub struct Foo { + foo: u64, + bar: T, +} + +// The store writing to bar.1 should have alignment 4. Not checking +// other stores here, as the alignment will be platform-dependent. + +// CHECK: store i32 [[TMP1:%.+]], i32* [[TMP2:%.+]], align 4 +#[no_mangle] +pub fn test(x: (i32, i32)) -> Foo<(i32, i32)> { + Foo { foo: 0, bar: x } +} From 5d7717360c8f343f70a33455029355f00e39dea2 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Tue, 27 Nov 2018 18:21:10 -0600 Subject: [PATCH 0326/1984] fix test --- src/test/ui/macros/macro-at-most-once-rep-2018.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr index 43779078ebc..da76d1ff1a7 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr +++ b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr @@ -41,7 +41,7 @@ LL | barplus!(); //~ERROR unexpected end of macro invocation | ^^^^^^^^^^^ missing tokens in macro arguments error: unexpected end of macro invocation - --> $DIR/macro-at-most-once-rep-2018.rs:41:15 + --> $DIR/macro-at-most-once-rep-2018.rs:39:15 | LL | macro_rules! barplus { | -------------------- when calling this macro @@ -77,7 +77,7 @@ LL | barstar!(); //~ERROR unexpected end of macro invocation | ^^^^^^^^^^^ missing tokens in macro arguments error: unexpected end of macro invocation - --> $DIR/macro-at-most-once-rep-2018.rs:46:14 + --> $DIR/macro-at-most-once-rep-2018.rs:46:15 | LL | macro_rules! barstar { | -------------------- when calling this macro From 12d90aa949f34712a374984bfaf88a5bf2f08685 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Nov 2018 09:29:56 +0100 Subject: [PATCH 0327/1984] put the MaybeUninit inside the UnsafeCell --- src/libcore/mem.rs | 3 --- src/libstd/sys/windows/mutex.rs | 17 +++++++---------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 626db7806df..b61a5c973a7 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -1106,9 +1106,6 @@ impl MaybeUninit { /// /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized /// state, otherwise this will immediately cause undefined behavior. - // FIXME: We currently rely on the above being incorrect, i.e., we have references - // to uninitialized data (e.g. in `libstd/sys/windows/mutex.rs`). We should make - // a final decision about the rules before stabilization. #[unstable(feature = "maybe_uninit", issue = "53491")] #[inline(always)] pub unsafe fn get_ref(&self) -> &T { diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 0c228f5097e..38ba0c7e035 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -157,37 +157,34 @@ fn kind() -> Kind { return ret; } -pub struct ReentrantMutex { inner: MaybeUninit> } +pub struct ReentrantMutex { inner: UnsafeCell> } unsafe impl Send for ReentrantMutex {} unsafe impl Sync for ReentrantMutex {} impl ReentrantMutex { pub fn uninitialized() -> ReentrantMutex { - ReentrantMutex { inner: MaybeUninit::uninitialized() } + ReentrantMutex { inner: UnsafeCell::new(MaybeUninit::uninitialized()) } } pub unsafe fn init(&mut self) { - // FIXME: Technically, this is calling `get_ref` on an uninitialized - // `MaybeUninit`. Revisit this once we decided whether that is valid - // or not. - c::InitializeCriticalSection(self.inner.get_ref().get()); + c::InitializeCriticalSection(self.inner.get().as_mut_ptr()); } pub unsafe fn lock(&self) { - c::EnterCriticalSection(self.inner.get_ref().get()); + c::EnterCriticalSection(self.inner.get().get_ref()); } #[inline] pub unsafe fn try_lock(&self) -> bool { - c::TryEnterCriticalSection(self.inner.get_ref().get()) != 0 + c::TryEnterCriticalSection(self.inner.get().get_ref()) != 0 } pub unsafe fn unlock(&self) { - c::LeaveCriticalSection(self.inner.get_ref().get()); + c::LeaveCriticalSection(self.inner.get().get_ref()); } pub unsafe fn destroy(&self) { - c::DeleteCriticalSection(self.inner.get_ref().get()); + c::DeleteCriticalSection(self.inner.get().get_ref()); } } From 965fdb029460346553cd9ddc59f5bb3b93e2f508 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Nov 2018 10:35:56 +0100 Subject: [PATCH 0328/1984] fix build --- src/libstd/sys/windows/mutex.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 38ba0c7e035..e54bbfca056 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -168,23 +168,31 @@ impl ReentrantMutex { } pub unsafe fn init(&mut self) { - c::InitializeCriticalSection(self.inner.get().as_mut_ptr()); + c::InitializeCriticalSection((&mut *self.inner.get()).as_mut_ptr()); } pub unsafe fn lock(&self) { - c::EnterCriticalSection(self.inner.get().get_ref()); + // `init` must have been called, so this is now initialized and + // we can call `get_ref`. + c::EnterCriticalSection((&mut *self.inner.get()).get_ref()); } #[inline] pub unsafe fn try_lock(&self) -> bool { - c::TryEnterCriticalSection(self.inner.get().get_ref()) != 0 + // `init` must have been called, so this is now initialized and + // we can call `get_ref`. + c::TryEnterCriticalSection((&mut *self.inner.get()).get_ref()) != 0 } pub unsafe fn unlock(&self) { - c::LeaveCriticalSection(self.inner.get().get_ref()); + // `init` must have been called, so this is now initialized and + // we can call `get_ref`. + c::LeaveCriticalSection((&mut *self.inner.get()).get_ref()); } pub unsafe fn destroy(&self) { - c::DeleteCriticalSection(self.inner.get().get_ref()); + // `init` must have been called, so this is now initialized and + // we can call `get_ref`. + c::DeleteCriticalSection((&mut *self.inner.get()).get_ref()); } } From dd593d3ab85826436dec593ce6ac06932291fd0e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Nov 2018 12:49:11 +0100 Subject: [PATCH 0329/1984] get_ref -> get_mut --- src/libstd/sys/windows/mutex.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index e54bbfca056..c2107c28e03 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -173,26 +173,26 @@ impl ReentrantMutex { pub unsafe fn lock(&self) { // `init` must have been called, so this is now initialized and - // we can call `get_ref`. - c::EnterCriticalSection((&mut *self.inner.get()).get_ref()); + // we can call `get_mut`. + c::EnterCriticalSection((&mut *self.inner.get()).get_mut()); } #[inline] pub unsafe fn try_lock(&self) -> bool { // `init` must have been called, so this is now initialized and - // we can call `get_ref`. - c::TryEnterCriticalSection((&mut *self.inner.get()).get_ref()) != 0 + // we can call `get_mut`. + c::TryEnterCriticalSection((&mut *self.inner.get()).get_mut()) != 0 } pub unsafe fn unlock(&self) { // `init` must have been called, so this is now initialized and - // we can call `get_ref`. - c::LeaveCriticalSection((&mut *self.inner.get()).get_ref()); + // we can call `get_mut`. + c::LeaveCriticalSection((&mut *self.inner.get()).get_mut()); } pub unsafe fn destroy(&self) { // `init` must have been called, so this is now initialized and - // we can call `get_ref`. - c::DeleteCriticalSection((&mut *self.inner.get()).get_ref()); + // we can call `get_mut`. + c::DeleteCriticalSection((&mut *self.inner.get()).get_mut()); } } From 8cab350c85b9738e4dbc99c67e71bd4a5b6f62a7 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Wed, 28 Nov 2018 23:59:19 +0900 Subject: [PATCH 0330/1984] Don't use ReErased in deferred sizedness checking. --- src/librustc_typeck/check/mod.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 44aa52651b0..a107cec9ef4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3970,7 +3970,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // // to work in stable even if the Sized bound on `drop` is relaxed. for i in 0..fn_sig.inputs().skip_binder().len() { - let input = tcx.erase_late_bound_regions(&fn_sig.input(i)); + // We just want to check sizedness, so instead of introducing + // placeholder lifetimes with probing, we just replace higher lifetimes + // with fresh vars. + let input = self.replace_bound_vars_with_fresh_vars( + expr.span, + infer::LateBoundRegionConversionTime::FnCall, + &fn_sig.input(i)).0; self.require_type_is_sized_deferred(input, expr.span, traits::SizedArgumentType); } @@ -3978,7 +3984,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Here we want to prevent struct constructors from returning unsized types. // There were two cases this happened: fn pointer coercion in stable // and usual function call in presense of unsized_locals. - let output = tcx.erase_late_bound_regions(&fn_sig.output()); + // Also, as we just want to check sizedness, instead of introducing + // placeholder lifetimes with probing, we just replace higher lifetimes + // with fresh vars. + let output = self.replace_bound_vars_with_fresh_vars( + expr.span, + infer::LateBoundRegionConversionTime::FnCall, + &fn_sig.output()).0; self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); } From 40412dc09a0fc4a4d2a38709614755b7b4be23da Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 28 Nov 2018 16:07:30 +0100 Subject: [PATCH 0331/1984] Deduplicate literal -> constant lowering --- src/librustc_mir/hair/cx/mod.rs | 67 ++++---------------- src/librustc_mir/hair/pattern/mod.rs | 91 ++++++++++------------------ 2 files changed, 45 insertions(+), 113 deletions(-) diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 733580b3ce2..ea1ec24c991 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -26,12 +26,12 @@ use rustc::ty::subst::Subst; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::{Kind, Substs}; use rustc::ty::layout::VariantIdx; -use syntax::ast::{self, LitKind}; +use syntax::ast; use syntax::attr; use syntax::symbol::Symbol; use rustc::hir; use rustc_data_structures::sync::Lrc; -use hair::pattern::parse_float; +use hair::pattern::{lit_to_const, LitToConstError}; #[derive(Clone)] pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { @@ -131,7 +131,6 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { ty::Const::from_bool(self.tcx, false) } - // FIXME: Combine with rustc_mir::hair::pattern::lit_to_const pub fn const_eval_literal( &mut self, lit: &'tcx ast::LitKind, @@ -141,61 +140,19 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { ) -> &'tcx ty::Const<'tcx> { trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg); - let parse_float = |num, fty| -> ConstValue<'tcx> { - parse_float(num, fty, neg).unwrap_or_else(|_| { + match lit_to_const(lit, self.tcx, ty, neg) { + Ok(c) => c, + Err(LitToConstError::UnparseableFloat) => { // FIXME(#31407) this is only necessary because float parsing is buggy - self.tcx.sess.span_fatal(sp, "could not evaluate float literal (see issue #31407)"); - }) - }; - - let trunc = |n| { - let param_ty = self.param_env.and(self.tcx.lift_to_global(&ty).unwrap()); - let width = self.tcx.layout_of(param_ty).unwrap().size; - trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); - let shift = 128 - width.bits(); - let result = (n << shift) >> shift; - trace!("trunc result: {}", result); - ConstValue::Scalar(Scalar::Bits { - bits: result, - size: width.bytes() as u8, - }) - }; - - use rustc::mir::interpret::*; - let lit = match *lit { - LitKind::Str(ref s, _) => { - let s = s.as_str(); - let id = self.tcx.allocate_bytes(s.as_bytes()); - ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &self.tcx) - }, - LitKind::ByteStr(ref data) => { - let id = self.tcx.allocate_bytes(data); - ConstValue::Scalar(Scalar::Ptr(id.into())) + self.tcx.sess.span_err(sp, "could not evaluate float literal (see issue #31407)"); + // create a dummy value and continue compiling + Const::from_bits(self.tcx, 0, self.param_env.and(ty)) }, - LitKind::Byte(n) => ConstValue::Scalar(Scalar::Bits { - bits: n as u128, - size: 1, - }), - LitKind::Int(n, _) if neg => { - let n = n as i128; - let n = n.overflowing_neg().0; - trunc(n as u128) - }, - LitKind::Int(n, _) => trunc(n), - LitKind::Float(n, fty) => { - parse_float(n, fty) - } - LitKind::FloatUnsuffixed(n) => { - let fty = match ty.sty { - ty::Float(fty) => fty, - _ => bug!() - }; - parse_float(n, fty) + Err(LitToConstError::Reported) => { + // create a dummy value and continue compiling + Const::from_bits(self.tcx, 0, self.param_env.and(ty)) } - LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)), - LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)), - }; - ty::Const::from_const_value(self.tcx, lit, ty) + } } pub fn pattern_from_hir(&mut self, p: &hir::Pat) -> Pattern<'tcx> { diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 941744c0aab..deea03acf0c 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -23,7 +23,7 @@ use hair::util::UserAnnotatedTyHelpers; use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability}; use rustc::mir::{ProjectionElem, UserTypeAnnotation, UserTypeProjection, UserTypeProjections}; use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend}; -use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty}; +use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, ParamEnv}; use rustc::ty::subst::{Substs, Kind}; use rustc::ty::layout::VariantIdx; use rustc::hir::{self, PatKind, RangeEnd}; @@ -891,12 +891,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ); *self.const_to_pat(instance, val, expr.hir_id, lit.span).kind }, - Err(e) => { - if e == LitToConstError::UnparseableFloat { - self.errors.push(PatternError::FloatBug); - } + Err(LitToConstError::UnparseableFloat) => { + self.errors.push(PatternError::FloatBug); PatternKind::Wild }, + Err(LitToConstError::Reported) => PatternKind::Wild, } }, hir::ExprKind::Path(ref qpath) => *self.lower_path(qpath, expr.hir_id, expr.span).kind, @@ -914,12 +913,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ); *self.const_to_pat(instance, val, expr.hir_id, lit.span).kind }, - Err(e) => { - if e == LitToConstError::UnparseableFloat { - self.errors.push(PatternError::FloatBug); - } + Err(LitToConstError::UnparseableFloat) => { + self.errors.push(PatternError::FloatBug); PatternKind::Wild }, + Err(LitToConstError::Reported) => PatternKind::Wild, } } _ => span_bug!(expr.span, "not a literal: {:?}", expr), @@ -1296,19 +1294,32 @@ pub fn compare_const_vals<'a, 'tcx>( } #[derive(PartialEq)] -enum LitToConstError { +pub enum LitToConstError { UnparseableFloat, - Propagated, + Reported, } -// FIXME: Combine with rustc_mir::hair::cx::const_eval_literal -fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - ty: Ty<'tcx>, - neg: bool) - -> Result<&'tcx ty::Const<'tcx>, LitToConstError> { +pub fn lit_to_const<'a, 'gcx, 'tcx>( + lit: &'tcx ast::LitKind, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + ty: Ty<'tcx>, + neg: bool, +) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> { use syntax::ast::*; + let trunc = |n| { + let param_ty = ParamEnv::reveal_all().and(tcx.lift_to_global(&ty).unwrap()); + let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size; + trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); + let shift = 128 - width.bits(); + let result = (n << shift) >> shift; + trace!("trunc result: {}", result); + Ok(ConstValue::Scalar(Scalar::Bits { + bits: result, + size: width.bytes() as u8, + })) + }; + use rustc::mir::interpret::*; let lit = match *lit { LitKind::Str(ref s, _) => { @@ -1324,48 +1335,12 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, bits: n as u128, size: 1, }), - LitKind::Int(n, _) => { - enum Int { - Signed(IntTy), - Unsigned(UintTy), - } - let ity = match ty.sty { - ty::Int(IntTy::Isize) => Int::Signed(tcx.sess.target.isize_ty), - ty::Int(other) => Int::Signed(other), - ty::Uint(UintTy::Usize) => Int::Unsigned(tcx.sess.target.usize_ty), - ty::Uint(other) => Int::Unsigned(other), - ty::Error => { // Avoid ICE (#51963) - return Err(LitToConstError::Propagated); - } - _ => bug!("literal integer type with bad type ({:?})", ty.sty), - }; - // This converts from LitKind::Int (which is sign extended) to - // Scalar::Bytes (which is zero extended) - let n = match ity { - // FIXME(oli-obk): are these casts correct? - Int::Signed(IntTy::I8) if neg => - (n as i8).overflowing_neg().0 as u8 as u128, - Int::Signed(IntTy::I16) if neg => - (n as i16).overflowing_neg().0 as u16 as u128, - Int::Signed(IntTy::I32) if neg => - (n as i32).overflowing_neg().0 as u32 as u128, - Int::Signed(IntTy::I64) if neg => - (n as i64).overflowing_neg().0 as u64 as u128, - Int::Signed(IntTy::I128) if neg => - (n as i128).overflowing_neg().0 as u128, - Int::Signed(IntTy::I8) | Int::Unsigned(UintTy::U8) => n as u8 as u128, - Int::Signed(IntTy::I16) | Int::Unsigned(UintTy::U16) => n as u16 as u128, - Int::Signed(IntTy::I32) | Int::Unsigned(UintTy::U32) => n as u32 as u128, - Int::Signed(IntTy::I64) | Int::Unsigned(UintTy::U64) => n as u64 as u128, - Int::Signed(IntTy::I128)| Int::Unsigned(UintTy::U128) => n, - _ => bug!(), - }; - let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size.bytes() as u8; - ConstValue::Scalar(Scalar::Bits { - bits: n, - size, - }) + LitKind::Int(n, _) if neg => { + let n = n as i128; + let n = n.overflowing_neg().0; + trunc(n as u128)? }, + LitKind::Int(n, _) => trunc(n)?, LitKind::Float(n, fty) => { parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)? } From 2ec76e76e487ffcc5cb3e2d540f1f48a806ccc57 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 28 Nov 2018 15:27:51 +0100 Subject: [PATCH 0332/1984] Update LLVM In particular to pull in a fix for #56265. --- src/llvm | 2 +- src/rustllvm/llvm-rebuild-trigger | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/llvm b/src/llvm index 21a0c9ebc28..a784eca10d2 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 21a0c9ebc285d794a298e97717abad8d6135fa87 +Subproject commit a784eca10d2c1f09e65d67e16eca266485e1eac3 diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index f8ff3d37fd2..9cf17c45e87 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2018-09-16 +2018-11-28 From c013de4f9b0e9197dc09f8e48ad970fcdf0dbea4 Mon Sep 17 00:00:00 2001 From: Lyndon Brown Date: Sat, 24 Nov 2018 23:56:27 +0000 Subject: [PATCH 0333/1984] rustdoc: add margin-bottom spacing to nested lists set to zero meant that the nested list was squished up against subsequent list items/paragraphs this changes the bottom margin to .6em, same as for paragraphs an example demonstrating the difference with screenshots is given in the pull request --- src/librustdoc/html/static/rustdoc.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index b2473dd9b23..a5b4a86ad8d 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -121,7 +121,7 @@ ol, ul { padding-left: 25px; } ul ul, ol ul, ul ol, ol ol { - margin-bottom: 0; + margin-bottom: .6em; } p { From 50b4eefcf5ce5e0a7808c6fc3f7effcea2e628c3 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Wed, 28 Nov 2018 17:10:21 +0100 Subject: [PATCH 0334/1984] rustdoc: Fix inlining reexported custom derives --- src/librustdoc/clean/inline.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 49cecd5b04b..464b6ea4fbe 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -106,13 +106,23 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa clean::ConstantItem(build_const(cx, did)) } // FIXME: proc-macros don't propagate attributes or spans across crates, so they look empty + Def::Macro(did, MacroKind::Derive) | Def::Macro(did, MacroKind::Bang) => { let mac = build_macro(cx, did, name); - if let clean::MacroItem(..) = mac { - record_extern_fqn(cx, did, clean::TypeKind::Macro); - mac - } else { - return None; + debug!("try_inline: {:?}", mac); + + match build_macro(cx, did, name) { + clean::MacroItem(..) => { + record_extern_fqn(cx, did, clean::TypeKind::Macro); + mac + } + clean::ProcMacroItem(..) => { + record_extern_fqn(cx, did, clean::TypeKind::Derive); + mac + } + _ => { + return None; + } } } _ => return None, From 230f5d5676ffad99e64f73128dc27f629aa8e921 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Wed, 28 Nov 2018 17:11:06 +0100 Subject: [PATCH 0335/1984] rustdoc: Fix inlining reexporting bang-macros --- src/librustdoc/visit_ast.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 5d221d3006f..b44b1d9e0ba 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -376,6 +376,10 @@ impl<'a, 'tcx, 'rcx, 'cstore> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> { }); true } + Node::MacroDef(def) if !glob => { + om.macros.push(self.visit_local_macro(def)); + true + } _ => false, }; self.view_item_stack.remove(&def_node_id); From afb8cba5fc611a652a674b44f1bbf26d200e1aa9 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 28 Nov 2018 17:15:40 +0100 Subject: [PATCH 0336/1984] Move hir::Lit -> ty::Const conversion into its own file --- src/librustc_mir/hair/constant.rs | 102 +++++++++++++++++++++++++++ src/librustc_mir/hair/cx/mod.rs | 2 +- src/librustc_mir/hair/mod.rs | 1 + src/librustc_mir/hair/pattern/mod.rs | 102 +-------------------------- 4 files changed, 106 insertions(+), 101 deletions(-) create mode 100644 src/librustc_mir/hair/constant.rs diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs new file mode 100644 index 00000000000..c98ef31c2ba --- /dev/null +++ b/src/librustc_mir/hair/constant.rs @@ -0,0 +1,102 @@ +use syntax::ast; +use rustc::ty::{self, Ty, TyCtxt, ParamEnv}; +use syntax_pos::symbol::Symbol; +use rustc::mir::interpret::{ConstValue, Scalar}; + +#[derive(PartialEq)] +crate enum LitToConstError { + UnparseableFloat, + Reported, +} + +crate fn lit_to_const<'a, 'gcx, 'tcx>( + lit: &'tcx ast::LitKind, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + ty: Ty<'tcx>, + neg: bool, +) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> { + use syntax::ast::*; + + let trunc = |n| { + let param_ty = ParamEnv::reveal_all().and(tcx.lift_to_global(&ty).unwrap()); + let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size; + trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); + let shift = 128 - width.bits(); + let result = (n << shift) >> shift; + trace!("trunc result: {}", result); + Ok(ConstValue::Scalar(Scalar::Bits { + bits: result, + size: width.bytes() as u8, + })) + }; + + use rustc::mir::interpret::*; + let lit = match *lit { + LitKind::Str(ref s, _) => { + let s = s.as_str(); + let id = tcx.allocate_bytes(s.as_bytes()); + ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx) + }, + LitKind::ByteStr(ref data) => { + let id = tcx.allocate_bytes(data); + ConstValue::Scalar(Scalar::Ptr(id.into())) + }, + LitKind::Byte(n) => ConstValue::Scalar(Scalar::Bits { + bits: n as u128, + size: 1, + }), + LitKind::Int(n, _) if neg => { + let n = n as i128; + let n = n.overflowing_neg().0; + trunc(n as u128)? + }, + LitKind::Int(n, _) => trunc(n)?, + LitKind::Float(n, fty) => { + parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)? + } + LitKind::FloatUnsuffixed(n) => { + let fty = match ty.sty { + ty::Float(fty) => fty, + _ => bug!() + }; + parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)? + } + LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)), + LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)), + }; + Ok(ty::Const::from_const_value(tcx, lit, ty)) +} + +fn parse_float<'tcx>( + num: Symbol, + fty: ast::FloatTy, + neg: bool, +) -> Result, ()> { + let num = num.as_str(); + use rustc_apfloat::ieee::{Single, Double}; + use rustc_apfloat::Float; + let (bits, size) = match fty { + ast::FloatTy::F32 => { + num.parse::().map_err(|_| ())?; + let mut f = num.parse::().unwrap_or_else(|e| { + panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) + }); + if neg { + f = -f; + } + (f.to_bits(), 4) + } + ast::FloatTy::F64 => { + num.parse::().map_err(|_| ())?; + let mut f = num.parse::().unwrap_or_else(|e| { + panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) + }); + if neg { + f = -f; + } + (f.to_bits(), 8) + } + }; + + Ok(ConstValue::Scalar(Scalar::Bits { bits, size })) +} diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index ea1ec24c991..c414088b653 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -31,7 +31,7 @@ use syntax::attr; use syntax::symbol::Symbol; use rustc::hir; use rustc_data_structures::sync::Lrc; -use hair::pattern::{lit_to_const, LitToConstError}; +use hair::constant::{lit_to_const, LitToConstError}; #[derive(Clone)] pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 3078f10598c..e604b118eac 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -26,6 +26,7 @@ use syntax_pos::Span; use self::cx::Cx; pub mod cx; +mod constant; pub mod pattern; pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern}; diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index deea03acf0c..61d8297fec9 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -19,11 +19,12 @@ pub(crate) use self::check_match::check_match; use const_eval::{const_field, const_variant_index}; use hair::util::UserAnnotatedTyHelpers; +use hair::constant::*; use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability}; use rustc::mir::{ProjectionElem, UserTypeAnnotation, UserTypeProjection, UserTypeProjections}; use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend}; -use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, ParamEnv}; +use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty}; use rustc::ty::subst::{Substs, Kind}; use rustc::ty::layout::VariantIdx; use rustc::hir::{self, PatKind, RangeEnd}; @@ -37,7 +38,6 @@ use std::fmt; use syntax::ast; use syntax::ptr::P; use syntax_pos::Span; -use syntax_pos::symbol::Symbol; #[derive(Clone, Debug)] pub enum PatternError { @@ -1292,101 +1292,3 @@ pub fn compare_const_vals<'a, 'tcx>( fallback() } - -#[derive(PartialEq)] -pub enum LitToConstError { - UnparseableFloat, - Reported, -} - -pub fn lit_to_const<'a, 'gcx, 'tcx>( - lit: &'tcx ast::LitKind, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - ty: Ty<'tcx>, - neg: bool, -) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> { - use syntax::ast::*; - - let trunc = |n| { - let param_ty = ParamEnv::reveal_all().and(tcx.lift_to_global(&ty).unwrap()); - let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size; - trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); - let shift = 128 - width.bits(); - let result = (n << shift) >> shift; - trace!("trunc result: {}", result); - Ok(ConstValue::Scalar(Scalar::Bits { - bits: result, - size: width.bytes() as u8, - })) - }; - - use rustc::mir::interpret::*; - let lit = match *lit { - LitKind::Str(ref s, _) => { - let s = s.as_str(); - let id = tcx.allocate_bytes(s.as_bytes()); - ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx) - }, - LitKind::ByteStr(ref data) => { - let id = tcx.allocate_bytes(data); - ConstValue::Scalar(Scalar::Ptr(id.into())) - }, - LitKind::Byte(n) => ConstValue::Scalar(Scalar::Bits { - bits: n as u128, - size: 1, - }), - LitKind::Int(n, _) if neg => { - let n = n as i128; - let n = n.overflowing_neg().0; - trunc(n as u128)? - }, - LitKind::Int(n, _) => trunc(n)?, - LitKind::Float(n, fty) => { - parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)? - } - LitKind::FloatUnsuffixed(n) => { - let fty = match ty.sty { - ty::Float(fty) => fty, - _ => bug!() - }; - parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)? - } - LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)), - LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)), - }; - Ok(ty::Const::from_const_value(tcx, lit, ty)) -} - -pub fn parse_float<'tcx>( - num: Symbol, - fty: ast::FloatTy, - neg: bool, -) -> Result, ()> { - let num = num.as_str(); - use rustc_apfloat::ieee::{Single, Double}; - use rustc_apfloat::Float; - let (bits, size) = match fty { - ast::FloatTy::F32 => { - num.parse::().map_err(|_| ())?; - let mut f = num.parse::().unwrap_or_else(|e| { - panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) - }); - if neg { - f = -f; - } - (f.to_bits(), 4) - } - ast::FloatTy::F64 => { - num.parse::().map_err(|_| ())?; - let mut f = num.parse::().unwrap_or_else(|e| { - panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) - }); - if neg { - f = -f; - } - (f.to_bits(), 8) - } - }; - - Ok(ConstValue::Scalar(Scalar::Bits { bits, size })) -} From f57247c48cb59a59dcfcb220251206064265479c Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 24 Oct 2018 00:57:09 -0400 Subject: [PATCH 0337/1984] Ensure that Rusdoc discovers all necessary auto trait bounds Fixes #50159 This commit makes several improvements to AutoTraitFinder: * Call infcx.resolve_type_vars_if_possible before processing new predicates. This ensures that we eliminate inference variables wherever possible. * Process all nested obligations we get from a vtable, not just ones with depth=1. * The 'depth=1' check was a hack to work around issues processing certain predicates. The other changes in this commit allow us to properly process all predicates that we encounter, so the check is no longer necessary, * Ensure that we only display predicates *without* inference variables to the user, and only attempt to unify predicates that *have* an inference variable as their type. Additionally, the internal helper method is_of_param now operates directly on a type, rather than taking a Substs. This allows us to use the 'self_ty' method, rather than directly dealing with Substs. --- src/librustc/traits/auto_trait.rs | 68 +++++++++++++++++++++++-------- src/test/rustdoc/issue-50159.rs | 31 ++++++++++++++ 2 files changed, 82 insertions(+), 17 deletions(-) create mode 100644 src/test/rustdoc/issue-50159.rs diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index c3cca149c2c..6279788adc0 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -334,7 +334,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { continue; } - let result = select.select(&Obligation::new(dummy_cause.clone(), new_env, pred)); + // Call infcx.resolve_type_vars_if_possible to see if we can + // get rid of any inference variables. + let obligation = infcx.resolve_type_vars_if_possible( + &Obligation::new(dummy_cause.clone(), new_env, pred) + ); + let result = select.select(&obligation); match &result { &Ok(Some(ref vtable)) => { @@ -369,7 +374,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } &Ok(None) => {} &Err(SelectionError::Unimplemented) => { - if self.is_of_param(pred.skip_binder().trait_ref.substs) { + if self.is_of_param(pred.skip_binder().self_ty()) { already_visited.remove(&pred); self.add_user_pred( &mut user_computed_preds, @@ -631,14 +636,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { finished_map } - pub fn is_of_param(&self, substs: &Substs<'_>) -> bool { - if substs.is_noop() { - return false; - } - - return match substs.type_at(0).sty { + pub fn is_of_param(&self, ty: Ty<'_>) -> bool { + return match ty.sty { ty::Param(_) => true, - ty::Projection(p) => self.is_of_param(p.substs), + ty::Projection(p) => self.is_of_param(p.self_ty()), _ => false, }; } @@ -661,28 +662,61 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { ) -> bool { let dummy_cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID); - for (obligation, predicate) in nested - .filter(|o| o.recursion_depth == 1) + for (obligation, mut predicate) in nested .map(|o| (o.clone(), o.predicate.clone())) { let is_new_pred = fresh_preds.insert(self.clean_pred(select.infcx(), predicate.clone())); + // Resolve any inference variables that we can, to help selection succeed + predicate = select.infcx().resolve_type_vars_if_possible(&predicate); + + // We only add a predicate as a user-displayable bound if + // it involves a generic parameter, and doesn't contain + // any inference variables. + // + // Displaying a bound involving a concrete type (instead of a generic + // parameter) would be pointless, since it's always true + // (e.g. u8: Copy) + // Displaying an inference variable is impossible, since they're + // an internal compiler detail without a defined visual representation + // + // We check this by calling is_of_param on the relevant types + // from the various possible predicates match &predicate { &ty::Predicate::Trait(ref p) => { - let substs = &p.skip_binder().trait_ref.substs; + if self.is_of_param(p.skip_binder().self_ty()) + && !only_projections + && is_new_pred { - if self.is_of_param(substs) && !only_projections && is_new_pred { self.add_user_pred(computed_preds, predicate); } predicates.push_back(p.clone()); } &ty::Predicate::Projection(p) => { - // If the projection isn't all type vars, then - // we don't want to add it as a bound - if self.is_of_param(p.skip_binder().projection_ty.substs) && is_new_pred { + debug!("evaluate_nested_obligations: examining projection predicate {:?}", + predicate); + + // As described above, we only want to display + // bounds which include a generic parameter but don't include + // an inference variable. + // Additionally, we check if we've seen this predicate before, + // to avoid rendering duplicate bounds to the user. + if self.is_of_param(p.skip_binder().projection_ty.self_ty()) + && !p.ty().skip_binder().is_ty_infer() + && is_new_pred { + debug!("evaluate_nested_obligations: adding projection predicate\ + to computed_preds: {:?}", predicate); + self.add_user_pred(computed_preds, predicate); - } else { + } + + // We can only call poly_project_and_unify_type when our predicate's + // Ty is an inference variable - otherwise, there won't be anything to + // unify + if p.ty().skip_binder().is_ty_infer() { + debug!("Projecting and unifying projection predicate {:?}", + predicate); match poly_project_and_unify_type(select, &obligation.with(p.clone())) { Err(e) => { debug!( diff --git a/src/test/rustdoc/issue-50159.rs b/src/test/rustdoc/issue-50159.rs new file mode 100644 index 00000000000..3055c721624 --- /dev/null +++ b/src/test/rustdoc/issue-50159.rs @@ -0,0 +1,31 @@ +// Copyright 2018 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. + + +pub trait Signal { + type Item; +} + +pub trait Signal2 { + type Item2; +} + +impl Signal2 for B where B: Signal { + type Item2 = C; +} + +// @has issue_50159/struct.Switch.html +// @has - '//code' 'impl Send for Switch where ::Item: Send' +// @has - '//code' 'impl Sync for Switch where ::Item: Sync' +// @count - '//*[@id="implementations-list"]/*[@class="impl"]' 0 +// @count - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]' 2 +pub struct Switch { + pub inner: ::Item2, +} From 1a84d211a2dad78f1d3412c65f5a72053a82893d Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 14 Nov 2018 16:36:48 -0500 Subject: [PATCH 0338/1984] Check all substitution parameters for inference variables --- src/librustc/traits/auto_trait.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index 6279788adc0..f560772e6c7 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -374,7 +374,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } &Ok(None) => {} &Err(SelectionError::Unimplemented) => { - if self.is_of_param(pred.skip_binder().self_ty()) { + if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) { already_visited.remove(&pred); self.add_user_pred( &mut user_computed_preds, @@ -636,6 +636,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { finished_map } + fn is_param_no_infer(&self, substs: &Substs<'_>) -> bool { + return self.is_of_param(substs.type_at(0)) && + !substs.types().any(|t| t.has_infer_types()); + } + pub fn is_of_param(&self, ty: Ty<'_>) -> bool { return match ty.sty { ty::Param(_) => true, @@ -685,7 +690,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // from the various possible predicates match &predicate { &ty::Predicate::Trait(ref p) => { - if self.is_of_param(p.skip_binder().self_ty()) + if self.is_param_no_infer(p.skip_binder().trait_ref.substs) && !only_projections && is_new_pred { @@ -702,7 +707,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // an inference variable. // Additionally, we check if we've seen this predicate before, // to avoid rendering duplicate bounds to the user. - if self.is_of_param(p.skip_binder().projection_ty.self_ty()) + if self.is_param_no_infer(p.skip_binder().projection_ty.substs) && !p.ty().skip_binder().is_ty_infer() && is_new_pred { debug!("evaluate_nested_obligations: adding projection predicate\ From 46a683111d4827800aae5eab4875c23089dce17e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Nov 2018 19:29:03 +0100 Subject: [PATCH 0339/1984] fix futures aliasing mutable and shared ref --- src/libstd/future.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/future.rs b/src/libstd/future.rs index 1cadbdc66c3..d5e6cab948b 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -95,10 +95,10 @@ where }); let _reset_waker = SetOnDrop(waker_ptr); - let mut waker_ptr = waker_ptr.expect( + let waker_ptr = waker_ptr.expect( "TLS LocalWaker not set. This is a rustc bug. \ Please file an issue on https://github.com/rust-lang/rust."); - unsafe { f(waker_ptr.as_mut()) } + unsafe { f(waker_ptr.as_ref()) } } #[unstable(feature = "gen_future", issue = "50547")] From dd717deccb3a4698beac8edb0a75e2efb6f08ebb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 1 Oct 2018 00:47:54 +0200 Subject: [PATCH 0340/1984] Add crate filtering --- src/librustdoc/html/layout.rs | 15 ++-- src/librustdoc/html/render.rs | 2 +- src/librustdoc/html/static/main.js | 99 +++++++++++++++++---- src/librustdoc/html/static/rustdoc.css | 24 ++++- src/librustdoc/html/static/themes/dark.css | 8 +- src/librustdoc/html/static/themes/light.css | 9 +- 6 files changed, 131 insertions(+), 26 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 6868c7707ad..d585b737517 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -81,11 +81,16 @@ pub fn render(

\
\ \
\
\ - \ + \