From 5eafae22ceb0e4fae835a5eb7518a55e75061e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 7 Dec 2018 16:18:38 +0200 Subject: [PATCH 01/34] Remove confusing comment about ideally using `!` for `c_void` Using `!` for `c_void` would have the problem that pointers and potentially references to an uninhabited type would be created, and at least for references this is UB. Also document in addition that newtype wrappers around `c_void` are not recommended for representing opaque types (as a workaround for `extern type` not being stable) but instead refer to the Nomicon. --- src/libcore/ffi.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index d7a112eb90df8..02e92af853452 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -13,11 +13,12 @@ use ::fmt; /// and `*mut c_void` is equivalent to C's `void*`. That said, this is /// *not* the same as C's `void` return type, which is Rust's `()` type. /// -/// Ideally, this type would be equivalent to [`!`], but currently it may -/// be more ideal to use `c_void` for FFI purposes. +/// To model pointers to opaque types in FFI, until `extern type` is +/// stabilized, it is recommended to use a newtype wrapper around an empty +/// byte array. See the [Nomicon] for details. /// -/// [`!`]: ../../std/primitive.never.html /// [pointer]: ../../std/primitive.pointer.html +/// [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs // N.B., for LLVM to recognize the void pointer type and by extension // functions like malloc(), we need to have it represented as i8* in // LLVM bitcode. The enum used here ensures this and prevents misuse From 8de8880b7b74cb0294c6d8c75c24656130278509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 10 Dec 2018 10:10:42 +0200 Subject: [PATCH 02/34] Update code comments of `c_void` to explain the reasoning for its current implementation We need at least two variants of the enum as otherwise the compiler complains about the #[repr(u8)] attribute and we also need at least one variant as otherwise the enum would be uninhabitated and dereferencing pointers to it would be UB. As such, mark the variants not unstable because they should not actually exist but because they are temporary implementation details until `extern type` is stable and can be used instead. --- src/libcore/ffi.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index 02e92af853452..22e219d51f41f 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -22,16 +22,18 @@ use ::fmt; // N.B., for LLVM to recognize the void pointer type and by extension // functions like malloc(), we need to have it represented as i8* in // LLVM bitcode. The enum used here ensures this and prevents misuse -// of the "raw" type by only having private variants.. We need two +// of the "raw" type by only having private variants. We need two // variants, because the compiler complains about the repr attribute -// otherwise. +// otherwise and we need at least one variant as otherwise the enum +// would be uninhabited and at least dereferencing such pointers would +// be UB. #[repr(u8)] #[stable(feature = "raw_os", since = "1.1.0")] pub enum c_void { - #[unstable(feature = "c_void_variant", reason = "should not have to exist", + #[unstable(feature = "c_void_variant", reason = "temporary implementation detail", issue = "0")] #[doc(hidden)] __variant1, - #[unstable(feature = "c_void_variant", reason = "should not have to exist", + #[unstable(feature = "c_void_variant", reason = "temporary implementation detail", issue = "0")] #[doc(hidden)] __variant2, } From 96678df83821407f2112028cc0099866cb548c49 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 5 Jan 2019 12:41:12 -0500 Subject: [PATCH 03/34] Cleanup PartialEq docs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Cleanup the `impl PartialEq for Book` implementation - Implement `impl PartialEq for BookFormat` so it’s symmetric - Fixes https://github.com/rust-lang/rust/issues/53844. - Removes the last example since it appears to be redundant with the previous two examples. --- src/libcore/cmp.rs | 56 ++++++++-------------------------------------- 1 file changed, 9 insertions(+), 47 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index f420d0d00a401..cf24e08e2e706 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -107,67 +107,29 @@ use self::Ordering::*; /// format: BookFormat, /// } /// +/// // Implement == comparisons /// impl PartialEq for Book { /// fn eq(&self, other: &BookFormat) -> bool { -/// match (&self.format, other) { -/// (BookFormat::Paperback, BookFormat::Paperback) => true, -/// (BookFormat::Hardback, BookFormat::Hardback) => true, -/// (BookFormat::Ebook, BookFormat::Ebook) => true, -/// (_, _) => false, -/// } +/// self.format == *other /// } /// } /// -/// let b1 = Book { isbn: 3, format: BookFormat::Paperback }; -/// -/// assert!(b1 == BookFormat::Paperback); -/// assert!(b1 != BookFormat::Ebook); -/// ``` -/// -/// By changing `impl PartialEq for Book` to `impl PartialEq for Book`, -/// we've changed what type we can use on the right side of the `==` operator. -/// This lets us use it in the `assert!` statements at the bottom. -/// -/// You can also combine these implementations to let the `==` operator work with -/// two different types: -/// -/// ``` -/// enum BookFormat { -/// Paperback, -/// Hardback, -/// Ebook, -/// } -/// -/// struct Book { -/// isbn: i32, -/// format: BookFormat, -/// } -/// -/// impl PartialEq for Book { -/// fn eq(&self, other: &BookFormat) -> bool { -/// match (&self.format, other) { -/// (&BookFormat::Paperback, &BookFormat::Paperback) => true, -/// (&BookFormat::Hardback, &BookFormat::Hardback) => true, -/// (&BookFormat::Ebook, &BookFormat::Ebook) => true, -/// (_, _) => false, -/// } -/// } -/// } -/// -/// impl PartialEq for Book { +/// // Implement == comparisons +/// impl PartialEq for BookFormat { /// fn eq(&self, other: &Book) -> bool { -/// self.isbn == other.isbn +/// *other == self.format /// } /// } /// /// let b1 = Book { isbn: 3, format: BookFormat::Paperback }; -/// let b2 = Book { isbn: 3, format: BookFormat::Ebook }; /// /// assert!(b1 == BookFormat::Paperback); -/// assert!(b1 != BookFormat::Ebook); -/// assert!(b1 == b2); +/// assert!(BookFormat::Ebook != b1); /// ``` /// +/// By changing `impl PartialEq for Book` to `impl PartialEq for Book`, +/// we allow `BookFormat`s to be compared with `Book`s. +/// /// # Examples /// /// ``` From 0d3dfdf6aadd7dd241956fa234bdd01de7291e5f Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 5 Jan 2019 22:52:13 -0500 Subject: [PATCH 04/34] Fix compile error --- src/libcore/cmp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index cf24e08e2e706..89afe7057b17b 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -117,7 +117,7 @@ use self::Ordering::*; /// // Implement == comparisons /// impl PartialEq for BookFormat { /// fn eq(&self, other: &Book) -> bool { -/// *other == self.format +/// *self == other.format /// } /// } /// From 319a2c1cc2a4d99d5b1d6fb424c77963fd668f24 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 6 Jan 2019 11:08:34 -0500 Subject: [PATCH 05/34] add missing derive to fix compile error --- src/libcore/cmp.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 89afe7057b17b..5b78aa632d17f 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -65,6 +65,7 @@ use self::Ordering::*; /// the same book if their ISBN matches, even if the formats differ: /// /// ``` +/// #[derive(PartialEq)] /// enum BookFormat { /// Paperback, /// Hardback, From bbbabdfc52eaa897c965bf10f50af4fc1512d4f0 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 6 Jan 2019 15:18:22 -0500 Subject: [PATCH 06/34] Update cmp.rs --- src/libcore/cmp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 5b78aa632d17f..64e37ec5a56cb 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -65,7 +65,6 @@ use self::Ordering::*; /// the same book if their ISBN matches, even if the formats differ: /// /// ``` -/// #[derive(PartialEq)] /// enum BookFormat { /// Paperback, /// Hardback, @@ -97,6 +96,7 @@ use self::Ordering::*; /// For example, let's tweak our previous code a bit: /// /// ``` +/// #[derive(PartialEq)] /// enum BookFormat { /// Paperback, /// Hardback, From 6c60662b26847a0d8670d298d6a5e95fade576df Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Fri, 4 Jan 2019 11:12:54 -0600 Subject: [PATCH 07/34] Use correct tracking issue for c_variadic Fixes #57306 --- src/libcore/ffi.rs | 22 +++++++++++----------- src/libstd/ffi/mod.rs | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index 0717a88b6b8f3..8a35051434dd4 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -49,7 +49,7 @@ impl fmt::Debug for c_void { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] extern { type VaListImpl; } @@ -74,7 +74,7 @@ impl fmt::Debug for VaListImpl { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] struct VaListImpl { stack: *mut (), gr_top: *mut (), @@ -90,7 +90,7 @@ struct VaListImpl { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] struct VaListImpl { gpr: u8, fpr: u8, @@ -106,7 +106,7 @@ struct VaListImpl { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] struct VaListImpl { gp_offset: i32, fp_offset: i32, @@ -120,7 +120,7 @@ struct VaListImpl { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] #[repr(transparent)] pub struct VaList<'a>(&'a mut VaListImpl); @@ -140,7 +140,7 @@ mod sealed_trait { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] pub trait VaArgSafe {} } @@ -150,7 +150,7 @@ macro_rules! impl_va_arg_safe { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] impl sealed_trait::VaArgSafe for $t {} )+ } @@ -163,12 +163,12 @@ 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")] + issue = "44930")] 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")] + issue = "44930")] impl sealed_trait::VaArgSafe for *const T {} impl<'a> VaList<'a> { @@ -176,7 +176,7 @@ impl<'a> VaList<'a> { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] pub unsafe fn arg(&mut self) -> T { va_arg(self) } @@ -185,7 +185,7 @@ impl<'a> VaList<'a> { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] pub unsafe fn copy(&self, f: F) -> R where F: for<'copy> FnOnce(VaList<'copy>) -> R { #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index 62081e713f139..7a38f0ebd5a57 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -169,7 +169,7 @@ pub use core::ffi::c_void; #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] pub use core::ffi::VaList; mod c_str; From 423a5bb5c437c2ce81d4150490d0cccfdbc33a4c Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 12 Jan 2019 11:00:14 -0500 Subject: [PATCH 08/34] add comment explaining what the derive does --- src/libcore/cmp.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 64e37ec5a56cb..72ff9cca9fd86 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -96,6 +96,7 @@ use self::Ordering::*; /// For example, let's tweak our previous code a bit: /// /// ``` +/// // The derive implements == comparisons /// #[derive(PartialEq)] /// enum BookFormat { /// Paperback, From 1445a065ded1bc7e73e7a358f9bc971e908e9181 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 12 Jan 2019 11:17:49 -0500 Subject: [PATCH 09/34] bring back the example i removed, also add symmetry and simplify impl --- src/libcore/cmp.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 72ff9cca9fd86..db72b7bb9d2da 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -132,6 +132,48 @@ use self::Ordering::*; /// By changing `impl PartialEq for Book` to `impl PartialEq for Book`, /// we allow `BookFormat`s to be compared with `Book`s. /// +/// You can also combine these implementations to let the `==` operator work with +/// two different types: +/// +/// ``` +/// #[derive(PartialEq)] +/// enum BookFormat { +/// Paperback, +/// Hardback, +/// Ebook, +/// } +/// +/// struct Book { +/// isbn: i32, +/// format: BookFormat, +/// } +/// +/// impl PartialEq for Book { +/// fn eq(&self, other: &BookFormat) -> bool { +/// self.format == *other +/// } +/// } +/// +/// impl PartialEq for BookFormat { +/// fn eq(&self, other: &Book) -> bool { +/// *self == other.format +/// } +/// } +/// +/// impl PartialEq for Book { +/// fn eq(&self, other: &Book) -> bool { +/// self.isbn == other.isbn +/// } +/// } +/// +/// let b1 = Book { isbn: 3, format: BookFormat::Paperback }; +/// let b2 = Book { isbn: 3, format: BookFormat::Ebook }; +/// +/// assert!(b1 == BookFormat::Paperback); +/// assert!(b1 != BookFormat::Ebook); +/// assert!(b1 == b2); +/// ``` +/// /// # Examples /// /// ``` From 0394dce7884562651906a84e3a32dc8ad2a50ac8 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 12 Jan 2019 11:19:02 -0500 Subject: [PATCH 10/34] whitespace --- src/libcore/cmp.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index db72b7bb9d2da..65792607a2824 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -142,33 +142,33 @@ use self::Ordering::*; /// Hardback, /// Ebook, /// } -/// +/// /// struct Book { /// isbn: i32, /// format: BookFormat, /// } -/// +/// /// impl PartialEq for Book { /// fn eq(&self, other: &BookFormat) -> bool { /// self.format == *other /// } /// } -/// +/// /// impl PartialEq for BookFormat { /// fn eq(&self, other: &Book) -> bool { /// *self == other.format /// } /// } -/// +/// /// impl PartialEq for Book { /// fn eq(&self, other: &Book) -> bool { /// self.isbn == other.isbn /// } /// } -/// +/// /// let b1 = Book { isbn: 3, format: BookFormat::Paperback }; /// let b2 = Book { isbn: 3, format: BookFormat::Ebook }; -/// +/// /// assert!(b1 == BookFormat::Paperback); /// assert!(b1 != BookFormat::Ebook); /// assert!(b1 == b2); From ebdd072e3b1d4b3eb39048c27be4e9b2ccc849a8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 13 Jan 2019 00:04:47 +0300 Subject: [PATCH 11/34] resolve: Add a test for issue #57539 --- src/test/ui/imports/issue-57539.rs | 8 ++++++++ src/test/ui/imports/issue-57539.stderr | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/test/ui/imports/issue-57539.rs create mode 100644 src/test/ui/imports/issue-57539.stderr diff --git a/src/test/ui/imports/issue-57539.rs b/src/test/ui/imports/issue-57539.rs new file mode 100644 index 0000000000000..90b74eb464779 --- /dev/null +++ b/src/test/ui/imports/issue-57539.rs @@ -0,0 +1,8 @@ +// edition:2018 + +mod core { + use core; //~ ERROR `core` is ambiguous + use crate::*; +} + +fn main() {} diff --git a/src/test/ui/imports/issue-57539.stderr b/src/test/ui/imports/issue-57539.stderr new file mode 100644 index 0000000000000..3f745fd8204bf --- /dev/null +++ b/src/test/ui/imports/issue-57539.stderr @@ -0,0 +1,18 @@ +error[E0659]: `core` is ambiguous (name vs any other name during import resolution) + --> $DIR/issue-57539.rs:4:9 + | +LL | use core; //~ ERROR `core` is ambiguous + | ^^^^ ambiguous name + | + = note: `core` could refer to a built-in extern crate + = help: use `::core` to refer to this extern crate unambiguously +note: `core` could also refer to the module imported here + --> $DIR/issue-57539.rs:5:9 + | +LL | use crate::*; + | ^^^^^^^^ + = help: use `self::core` to refer to this module unambiguously + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. From c6632725c1c72569eb8f017461809648fd9e9c93 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Tue, 13 Nov 2018 16:25:51 -0800 Subject: [PATCH 12/34] Support passing cflags/cxxflags/ldflags to LLVM build This may be needed with some host compilers. --- config.toml.example | 5 +++++ src/bootstrap/config.rs | 10 ++++++++++ src/bootstrap/configure.py | 4 ++++ src/bootstrap/native.rs | 15 ++++++++++++++- 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/config.toml.example b/config.toml.example index 23943d34b7ca8..24293fc864c5f 100644 --- a/config.toml.example +++ b/config.toml.example @@ -90,6 +90,11 @@ # with clang-cl, so this is special in that it only compiles LLVM with clang-cl #clang-cl = '/path/to/clang-cl.exe' +# Pass extra compiler and linker flags to the LLVM CMake build. +#cflags = "-fextra-flag" +#cxxflags = "-fextra-flag" +#ldflags = "-Wl,extra-flag" + # Use libc++ when building LLVM instead of libstdc++. This is the default on # platforms already use libc++ as the default C++ library, but this option # allows you to use libc++ even on platforms when it's not. You need to ensure diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 9421817ae6d8e..a2989f0cffa6e 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -82,6 +82,9 @@ pub struct Config { pub lldb_enabled: bool, pub llvm_tools_enabled: bool, + pub llvm_cflags: Option, + pub llvm_cxxflags: Option, + pub llvm_ldflags: Option, pub llvm_use_libcxx: bool, // rust codegen options @@ -254,6 +257,9 @@ struct Llvm { link_shared: Option, version_suffix: Option, clang_cl: Option, + cflags: Option, + cxxflags: Option, + ldflags: Option, use_libcxx: Option, } @@ -516,6 +522,10 @@ impl Config { config.llvm_link_jobs = llvm.link_jobs; config.llvm_version_suffix = llvm.version_suffix.clone(); config.llvm_clang_cl = llvm.clang_cl.clone(); + + config.llvm_cflags = llvm.cflags.clone(); + config.llvm_cxxflags = llvm.cxxflags.clone(); + config.llvm_ldflags = llvm.ldflags.clone(); set(&mut config.llvm_use_libcxx, llvm.use_libcxx); } diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index b0c3c9702498d..7b70236dfe8e6 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -64,6 +64,10 @@ def v(*args): o("missing-tools", "dist.missing-tools", "allow failures when building tools") o("use-libcxx", "llvm.use_libcxx", "build LLVM with libc++") +o("cflags", "llvm.cflags", "build LLVM with these extra compiler flags") +o("cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags") +o("ldflags", "llvm.ldflags", "build LLVM with these extra linker flags") + # Optimization and debugging options. These may be overridden by the release # channel, etc. o("optimize", "rust.optimize", "build optimized rust code") diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index cb9c86df55080..f5bacd63e6803 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -358,7 +358,11 @@ fn configure_cmake(builder: &Builder, } cfg.build_arg("-j").build_arg(builder.jobs().to_string()); - cfg.define("CMAKE_C_FLAGS", builder.cflags(target, GitRepo::Llvm).join(" ")); + let mut cflags = builder.cflags(target, GitRepo::Llvm).join(" "); + if let Some(ref s) = builder.config.llvm_cxxflags { + cflags.push_str(&format!(" {}", s)); + } + cfg.define("CMAKE_C_FLAGS", cflags); let mut cxxflags = builder.cflags(target, GitRepo::Llvm).join(" "); if builder.config.llvm_static_stdcpp && !target.contains("windows") && @@ -366,6 +370,9 @@ fn configure_cmake(builder: &Builder, { cxxflags.push_str(" -static-libstdc++"); } + if let Some(ref s) = builder.config.llvm_cxxflags { + cxxflags.push_str(&format!(" {}", s)); + } cfg.define("CMAKE_CXX_FLAGS", cxxflags); if let Some(ar) = builder.ar(target) { if ar.is_absolute() { @@ -383,6 +390,12 @@ fn configure_cmake(builder: &Builder, } } + if let Some(ref s) = builder.config.llvm_ldflags { + cfg.define("CMAKE_SHARED_LINKER_FLAGS", s); + cfg.define("CMAKE_MODULE_LINKER_FLAGS", s); + cfg.define("CMAKE_EXE_LINKER_FLAGS", s); + } + if env::var_os("SCCACHE_ERROR_LOG").is_some() { cfg.env("RUST_LOG", "sccache=warn"); } From f4ded5b5591b3ec1446422dd9d62d404d4335753 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Mon, 24 Dec 2018 16:07:10 -0700 Subject: [PATCH 13/34] Add a regression test for mutating a non-mut #[thread_local] --- src/test/ui/thread-local-mutation.nll.stderr | 9 +++++++++ src/test/ui/thread-local-mutation.rs | 18 ++++++++++++++++++ src/test/ui/thread-local-mutation.stderr | 9 +++++++++ 3 files changed, 36 insertions(+) create mode 100644 src/test/ui/thread-local-mutation.nll.stderr create mode 100644 src/test/ui/thread-local-mutation.rs create mode 100644 src/test/ui/thread-local-mutation.stderr diff --git a/src/test/ui/thread-local-mutation.nll.stderr b/src/test/ui/thread-local-mutation.nll.stderr new file mode 100644 index 0000000000000..0a3664b0d9d40 --- /dev/null +++ b/src/test/ui/thread-local-mutation.nll.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to immutable static item `S` + --> $DIR/thread-local-mutation.rs:11:5 + | +LL | S = "after"; //~ ERROR cannot assign to immutable + | ^^^^^^^^^^^ cannot assign + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/thread-local-mutation.rs b/src/test/ui/thread-local-mutation.rs new file mode 100644 index 0000000000000..e738225ce2a48 --- /dev/null +++ b/src/test/ui/thread-local-mutation.rs @@ -0,0 +1,18 @@ +// Regression test for #54901: immutable thread locals could be mutated. See: +// https://github.com/rust-lang/rust/issues/29594#issuecomment-328177697 +// https://github.com/rust-lang/rust/issues/54901 + +#![feature(thread_local)] + +#[thread_local] +static S: &str = "before"; + +fn set_s() { + S = "after"; //~ ERROR cannot assign to immutable +} + +fn main() { + println!("{}", S); + set_s(); + println!("{}", S); +} diff --git a/src/test/ui/thread-local-mutation.stderr b/src/test/ui/thread-local-mutation.stderr new file mode 100644 index 0000000000000..bf298523e1b73 --- /dev/null +++ b/src/test/ui/thread-local-mutation.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to immutable thread-local static item + --> $DIR/thread-local-mutation.rs:11:5 + | +LL | S = "after"; //~ ERROR cannot assign to immutable + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. From e5e9867f604b9f656d529deb04a6b99338770c9e Mon Sep 17 00:00:00 2001 From: AB1908 Date: Tue, 15 Jan 2019 08:26:29 +0000 Subject: [PATCH 14/34] Pass a default value when unwrapping a span Fixes #57323 --- src/librustc_metadata/native_libs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index d35d64957b7b4..1f00086e32fe1 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -163,7 +163,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> { !self.tcx.features().static_nobundle { feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, "static_nobundle", - span.unwrap(), + span.unwrap_or_else(|| syntax_pos::DUMMY_SP), GateIssue::Language, "kind=\"static-nobundle\" is feature gated"); } From 096ca873330d61de91d81618ce3a1e9905581ff1 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 15 Jan 2019 17:11:07 +0100 Subject: [PATCH 15/34] Remove an unused function argument --- src/librustc/hir/intravisit.rs | 58 +-------------------- src/librustc_borrowck/borrowck/mod.rs | 9 ---- src/librustc_borrowck/borrowck/move_data.rs | 4 -- src/librustc_borrowck/dataflow.rs | 7 ++- 4 files changed, 4 insertions(+), 74 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index f633703be56d4..041291e80eee9 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -35,11 +35,9 @@ use syntax::ast::{NodeId, CRATE_NODE_ID, Ident, Name, Attribute}; use syntax_pos::Span; use hir::*; use hir::def::Def; -use hir::map::{self, Map}; +use hir::map::Map; use super::itemlikevisit::DeepVisitor; -use std::cmp; - #[derive(Copy, Clone)] pub enum FnKind<'a> { /// `#[xxx] pub async/const/extern "Abi" fn foo()` @@ -1133,57 +1131,3 @@ pub fn walk_defaultness<'v, V: Visitor<'v>>(_: &mut V, _: &'v Defaultness) { // the right thing to do, should content be added in the future, // would be to walk it. } - -#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct IdRange { - pub min: NodeId, - pub max: NodeId, -} - -impl IdRange { - pub fn max() -> IdRange { - IdRange { - min: NodeId::MAX, - max: NodeId::from_u32(0), - } - } - - pub fn empty(&self) -> bool { - self.min >= self.max - } - - pub fn contains(&self, id: NodeId) -> bool { - id >= self.min && id < self.max - } - - pub fn add(&mut self, id: NodeId) { - self.min = cmp::min(self.min, id); - self.max = cmp::max(self.max, NodeId::from_u32(id.as_u32() + 1)); - } -} - - -pub struct IdRangeComputingVisitor<'a, 'hir: 'a> { - result: IdRange, - map: &'a map::Map<'hir>, -} - -impl<'a, 'hir> IdRangeComputingVisitor<'a, 'hir> { - pub fn new(map: &'a map::Map<'hir>) -> IdRangeComputingVisitor<'a, 'hir> { - IdRangeComputingVisitor { result: IdRange::max(), map: map } - } - - pub fn result(&self) -> IdRange { - self.result - } -} - -impl<'a, 'hir> Visitor<'hir> for IdRangeComputingVisitor<'a, 'hir> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> { - NestedVisitorMap::OnlyBodies(&self.map) - } - - fn visit_id(&mut self, id: NodeId) { - self.result.add(id); - } -} diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 66303ab71b25f..72963cb7e7fb4 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -39,7 +39,6 @@ use syntax_pos::{MultiSpan, Span}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use rustc::hir; -use rustc::hir::intravisit::{self, Visitor}; use dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom}; @@ -157,12 +156,6 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc where F: FnOnce(&mut BorrowckCtxt<'a, 'tcx>) -> &'c cfg::CFG { // Check the body of fn items. - let tcx = this.tcx; - let id_range = { - let mut visitor = intravisit::IdRangeComputingVisitor::new(&tcx.hir()); - visitor.visit_body(this.body); - visitor.result() - }; let (all_loans, move_data) = gather_loans::gather_loans_in_fn(this, body_id); @@ -184,7 +177,6 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc Some(this.body), cfg, LoanDataFlowOperator, - id_range, all_loans.len()); for (loan_idx, loan) in all_loans.iter().enumerate() { loan_dfcx.add_gen(loan.gen_scope.item_local_id(), loan_idx); @@ -198,7 +190,6 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc let flowed_moves = move_data::FlowedMoveData::new(move_data, this, cfg, - id_range, this.body); Some(AnalysisData { all_loans, diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index c5bee87e90fe4..56c9f928eb03a 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -15,7 +15,6 @@ use std::rc::Rc; use std::usize; use syntax_pos::Span; use rustc::hir; -use rustc::hir::intravisit::IdRange; #[derive(Default)] pub struct MoveData<'tcx> { @@ -559,7 +558,6 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { pub fn new(move_data: MoveData<'tcx>, bccx: &BorrowckCtxt<'a, 'tcx>, cfg: &cfg::CFG, - id_range: IdRange, body: &hir::Body) -> FlowedMoveData<'a, 'tcx> { let tcx = bccx.tcx; @@ -570,7 +568,6 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { Some(body), cfg, MoveDataFlowOperator, - id_range, move_data.moves.borrow().len()); let mut dfcx_assign = DataFlowContext::new(tcx, @@ -578,7 +575,6 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { Some(body), cfg, AssignDataFlowOperator, - id_range, move_data.var_assignments.borrow().len()); move_data.add_gen_kills(bccx, diff --git a/src/librustc_borrowck/dataflow.rs b/src/librustc_borrowck/dataflow.rs index 56e25bd89c9ad..8cf620567405c 100644 --- a/src/librustc_borrowck/dataflow.rs +++ b/src/librustc_borrowck/dataflow.rs @@ -15,7 +15,7 @@ use rustc_data_structures::graph::implementation::OUTGOING; use rustc::util::nodemap::FxHashMap; use rustc::hir; -use rustc::hir::intravisit::{self, IdRange}; +use rustc::hir::intravisit; use rustc::hir::print as pprust; @@ -230,16 +230,15 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { body: Option<&hir::Body>, cfg: &cfg::CFG, oper: O, - id_range: IdRange, bits_per_id: usize) -> DataFlowContext<'a, 'tcx, O> { let usize_bits = mem::size_of::() * 8; let words_per_id = (bits_per_id + usize_bits - 1) / usize_bits; let num_nodes = cfg.graph.all_nodes().len(); - debug!("DataFlowContext::new(analysis_name: {}, id_range={:?}, \ + debug!("DataFlowContext::new(analysis_name: {}, \ bits_per_id={}, words_per_id={}) \ num_nodes: {}", - analysis_name, id_range, bits_per_id, words_per_id, + analysis_name, bits_per_id, words_per_id, num_nodes); let entry = if oper.initial_value() { usize::MAX } else {0}; From 93b55365b59767f87ac2a2e42876ad46210a0e55 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Tue, 15 Jan 2019 11:27:58 -0500 Subject: [PATCH 16/34] use structured macro and path resolve suggestions --- src/librustc_resolve/lib.rs | 24 ++++++++++--- src/test/ui/resolve/resolve-hint-macro.stderr | 2 +- ...uggest-path-instead-of-mod-dot-item.stderr | 36 ++++++++++++------- .../try-block/try-block-in-edition2015.stderr | 2 +- 4 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a25009ccfb49c..439d149227203 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3321,7 +3321,12 @@ impl<'a> Resolver<'a> { if let Some(def) = def { match (def, source) { (Def::Macro(..), _) => { - err.span_label(span, format!("did you mean `{}!(...)`?", path_str)); + err.span_suggestion_with_applicability( + span, + "use `!` to invoke the macro", + format!("{}!", path_str), + Applicability::MaybeIncorrect, + ); return (err, candidates); } (Def::TyAlias(..), PathSource::Trait(_)) => { @@ -3333,13 +3338,22 @@ impl<'a> Resolver<'a> { } (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node { ExprKind::Field(_, ident) => { - err.span_label(parent.span, format!("did you mean `{}::{}`?", - path_str, ident)); + err.span_suggestion_with_applicability( + parent.span, + "use the path separator to refer to an item", + format!("{}::{}", path_str, ident), + Applicability::MaybeIncorrect, + ); return (err, candidates); } ExprKind::MethodCall(ref segment, ..) => { - err.span_label(parent.span, format!("did you mean `{}::{}(...)`?", - path_str, segment.ident)); + let span = parent.span.with_hi(segment.ident.span.hi()); + err.span_suggestion_with_applicability( + span, + "use the path separator to refer to an item", + format!("{}::{}", path_str, segment.ident), + Applicability::MaybeIncorrect, + ); return (err, candidates); } _ => {} diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr index 4f6d0f695df44..ebe3c36f21eb1 100644 --- a/src/test/ui/resolve/resolve-hint-macro.stderr +++ b/src/test/ui/resolve/resolve-hint-macro.stderr @@ -2,7 +2,7 @@ error[E0423]: expected function, found macro `assert` --> $DIR/resolve-hint-macro.rs:2:5 | LL | assert(true); - | ^^^^^^ did you mean `assert!(...)`? + | ^^^^^^ help: use `!` to invoke the macro: `assert!` error: aborting due to previous error diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr index 8a9426bfee862..b7b158ce7efa6 100644 --- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr +++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr @@ -4,15 +4,15 @@ error[E0423]: expected value, found module `a` LL | a.I | ^-- | | - | did you mean `a::I`? + | help: use the path separator to refer to an item: `a::I` error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:22:5 | LL | a.g() - | ^---- + | ^-- | | - | did you mean `a::g(...)`? + | help: use the path separator to refer to an item: `a::g` error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5 @@ -20,16 +20,21 @@ error[E0423]: expected value, found module `a` LL | a.b.J | ^-- | | - | did you mean `a::b`? + | help: use the path separator to refer to an item: `a::b` error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:32:5 | LL | a::b.J - | ^^^--- - | | | - | | help: a constant with a similar name exists: `I` - | did you mean `a::b::J`? + | ^^^^ +help: a constant with a similar name exists + | +LL | a::I.J + | ^ +help: use the path separator to refer to an item + | +LL | a::b::J + | error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:37:5 @@ -37,7 +42,7 @@ error[E0423]: expected value, found module `a` LL | a.b.f(); | ^-- | | - | did you mean `a::b`? + | help: use the path separator to refer to an item: `a::b` error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:40:12 @@ -51,10 +56,15 @@ error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5 | LL | a::b.f() - | ^^^----- - | | | - | | help: a constant with a similar name exists: `I` - | did you mean `a::b::f(...)`? + | ^^^^ +help: a constant with a similar name exists + | +LL | a::I.f() + | ^ +help: use the path separator to refer to an item + | +LL | a::b::f() + | ^^^^^^^ error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:50:5 diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr index 63650086bcaa9..a7b81060d3dc6 100644 --- a/src/test/ui/try-block/try-block-in-edition2015.stderr +++ b/src/test/ui/try-block/try-block-in-edition2015.stderr @@ -15,7 +15,7 @@ error[E0574]: expected struct, variant or union type, found macro `try` --> $DIR/try-block-in-edition2015.rs:4:33 | LL | let try_result: Option<_> = try { - | ^^^ did you mean `try!(...)`? + | ^^^ help: use `!` to invoke the macro: `try!` error: aborting due to 2 previous errors From ed717f30ec3006e465ed4d68adf31cabdf0329fa Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 15 Jan 2019 17:57:06 +0100 Subject: [PATCH 17/34] Fix sources sidebar not showing up --- src/librustdoc/html/render.rs | 2 +- src/librustdoc/html/static/source-script.js | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 31e06cb1a045f..1d50afe2821ac 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1042,7 +1042,7 @@ themePicker.onblur = handleThemeButtonsBlur; all_sources.sort(); let mut w = try_err!(File::create(&dst), &dst); try_err!(writeln!(&mut w, - "var N = null;var sourcesIndex = {{}};\n{}", + "var N = null;var sourcesIndex = {{}};\n{}\ncreateSourceSidebar();", all_sources.join("\n")), &dst); } diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js index 0affe1c6812f5..c5d6fa16f550e 100644 --- a/src/librustdoc/html/static/source-script.js +++ b/src/librustdoc/html/static/source-script.js @@ -137,5 +137,3 @@ function createSourceSidebar() { main.insertBefore(sidebar, main.firstChild); } - -createSourceSidebar(); From 6046be42ab911cf2eddd41cffaa0467098bb2317 Mon Sep 17 00:00:00 2001 From: mark Date: Mon, 14 Jan 2019 15:50:33 -0600 Subject: [PATCH 18/34] fix nested matchers with ? --- src/libsyntax/ext/tt/macro_rules.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 24202ca8fbdc0..9a129e7e8fcd8 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -435,7 +435,8 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool { match *seq_tt { TokenTree::MetaVarDecl(_, _, id) => id.name == "vis", TokenTree::Sequence(_, ref sub_seq) => - sub_seq.op == quoted::KleeneOp::ZeroOrMore, + sub_seq.op == quoted::KleeneOp::ZeroOrMore + || sub_seq.op == quoted::KleeneOp::ZeroOrOne, _ => false, } }) { @@ -543,7 +544,10 @@ impl FirstSets { } // Reverse scan: Sequence comes before `first`. - if subfirst.maybe_empty || seq_rep.op == quoted::KleeneOp::ZeroOrMore { + if subfirst.maybe_empty + || seq_rep.op == quoted::KleeneOp::ZeroOrMore + || seq_rep.op == quoted::KleeneOp::ZeroOrOne + { // If sequence is potentially empty, then // union them (preserving first emptiness). first.add_all(&TokenSet { maybe_empty: true, ..subfirst }); @@ -591,8 +595,10 @@ impl FirstSets { assert!(first.maybe_empty); first.add_all(subfirst); - if subfirst.maybe_empty || - seq_rep.op == quoted::KleeneOp::ZeroOrMore { + if subfirst.maybe_empty + || seq_rep.op == quoted::KleeneOp::ZeroOrMore + || seq_rep.op == quoted::KleeneOp::ZeroOrOne + { // continue scanning for more first // tokens, but also make sure we // restore empty-tracking state From dabe86db44c97698bc6a4ab2f8923a3f65b151f0 Mon Sep 17 00:00:00 2001 From: mark Date: Tue, 15 Jan 2019 11:31:49 -0600 Subject: [PATCH 19/34] update/add tests --- src/test/ui/issues/issue-5067.rs | 37 ++++++++++--- src/test/ui/issues/issue-57597.rs | 80 +++++++++++++++++++++++++++ src/test/ui/issues/issue-57597.stderr | 74 +++++++++++++++++++++++++ 3 files changed, 183 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/issues/issue-57597.rs create mode 100644 src/test/ui/issues/issue-57597.stderr diff --git a/src/test/ui/issues/issue-5067.rs b/src/test/ui/issues/issue-5067.rs index 526a68311462e..616fd09907a2b 100644 --- a/src/test/ui/issues/issue-5067.rs +++ b/src/test/ui/issues/issue-5067.rs @@ -1,37 +1,59 @@ #![allow(unused_macros)] +// Tests that repetition matchers cannot match the empty token tree (since that would be +// ambiguous). + +// edition:2018 + macro_rules! foo { ( $()* ) => {}; //~^ ERROR repetition matches empty token tree ( $()+ ) => {}; //~^ ERROR repetition matches empty token tree - + ( $()? ) => {}; + //~^ ERROR repetition matches empty token tree ( $(),* ) => {}; // PASS ( $(),+ ) => {}; // PASS - + // `?` cannot have a separator... ( [$()*] ) => {}; //~^ ERROR repetition matches empty token tree ( [$()+] ) => {}; //~^ ERROR repetition matches empty token tree - + ( [$()?] ) => {}; + //~^ ERROR repetition matches empty token tree ( [$(),*] ) => {}; // PASS ( [$(),+] ) => {}; // PASS - + // `?` cannot have a separator... ( $($()* $(),* $(a)* $(a),* )* ) => {}; //~^ ERROR repetition matches empty token tree ( $($()* $(),* $(a)* $(a),* )+ ) => {}; //~^ ERROR repetition matches empty token tree - + ( $($()* $(),* $(a)* $(a),* )? ) => {}; + //~^ ERROR repetition matches empty token tree + ( $($()? $(),* $(a)? $(a),* )* ) => {}; + //~^ ERROR repetition matches empty token tree + ( $($()? $(),* $(a)? $(a),* )+ ) => {}; + //~^ ERROR repetition matches empty token tree + ( $($()? $(),* $(a)? $(a),* )? ) => {}; + //~^ ERROR repetition matches empty token tree ( $(a $(),* $(a)* $(a),* )* ) => {}; // PASS ( $($(a)+ $(),* $(a)* $(a),* )+ ) => {}; // PASS + ( $($(a)+ $(),* $(a)* $(a),* )? ) => {}; // PASS + + ( $(a $(),* $(a)? $(a),* )* ) => {}; // PASS + ( $($(a)+ $(),* $(a)? $(a),* )+ ) => {}; // PASS + ( $($(a)+ $(),* $(a)? $(a),* )? ) => {}; // PASS ( $(a $()+)* ) => {}; //~^ ERROR repetition matches empty token tree ( $(a $()*)+ ) => {}; //~^ ERROR repetition matches empty token tree + ( $(a $()+)? ) => {}; + //~^ ERROR repetition matches empty token tree + ( $(a $()?)+ ) => {}; + //~^ ERROR repetition matches empty token tree } - // --- Original Issue --- // macro_rules! make_vec { @@ -43,11 +65,10 @@ fn main() { let _ = make_vec![a 1, a 2, a 3]; } - // --- Minified Issue --- // macro_rules! m { - ( $()* ) => {} + ( $()* ) => {}; //~^ ERROR repetition matches empty token tree } diff --git a/src/test/ui/issues/issue-57597.rs b/src/test/ui/issues/issue-57597.rs new file mode 100644 index 0000000000000..ebeb3fe07adb4 --- /dev/null +++ b/src/test/ui/issues/issue-57597.rs @@ -0,0 +1,80 @@ +// Regression test for #57597. +// +// Make sure that nested matchers work correctly rather than causing an infinite loop or crash. + +// edition:2018 + +macro_rules! foo1 { + ($($($i:ident)?)+) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo2 { + ($($($i:ident)?)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo3 { + ($($($i:ident)?)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo4 { + ($($($($i:ident)?)?)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo5 { + ($($($($i:ident)*)?)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo6 { + ($($($($i:ident)?)*)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo7 { + ($($($($i:ident)?)?)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo8 { + ($($($($i:ident)*)*)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo9 { + ($($($($i:ident)?)*)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo10 { + ($($($($i:ident)?)*)+) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo11 { + ($($($($i:ident)+)?)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo12 { + ($($($($i:ident)+)*)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +fn main() { + foo1!(); + foo2!(); + foo3!(); + foo4!(); + foo5!(); + foo6!(); + foo7!(); + foo8!(); + foo9!(); + foo10!(); + foo11!(); + foo12!(); +} diff --git a/src/test/ui/issues/issue-57597.stderr b/src/test/ui/issues/issue-57597.stderr new file mode 100644 index 0000000000000..0a02ac8c499b6 --- /dev/null +++ b/src/test/ui/issues/issue-57597.stderr @@ -0,0 +1,74 @@ +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:8:7 + | +LL | ($($($i:ident)?)+) => {}; + | ^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:13:7 + | +LL | ($($($i:ident)?)*) => {}; + | ^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:18:7 + | +LL | ($($($i:ident)?)?) => {}; + | ^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:23:7 + | +LL | ($($($($i:ident)?)?)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:28:7 + | +LL | ($($($($i:ident)*)?)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:33:7 + | +LL | ($($($($i:ident)?)*)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:38:7 + | +LL | ($($($($i:ident)?)?)*) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:43:7 + | +LL | ($($($($i:ident)*)*)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:48:7 + | +LL | ($($($($i:ident)?)*)*) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:53:7 + | +LL | ($($($($i:ident)?)*)+) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:58:7 + | +LL | ($($($($i:ident)+)?)*) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:63:7 + | +LL | ($($($($i:ident)+)*)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + From feda6040faa854f6bbe6ab9c7f11b59ec21ec1d1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 15 Jan 2019 23:21:10 +0100 Subject: [PATCH 20/34] Fixes text becoming invisible when element targetted --- src/librustdoc/html/static/themes/dark.css | 8 +------- src/librustdoc/html/static/themes/light.css | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 1390be700634d..52a30967a2310 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -82,12 +82,6 @@ pre { border-bottom-color: #ddd; } -:target { background: #494a3d; } - -:target > .in-band { - background: #494a3d; -} - .content .method .where, .content .fn .where, .content .where.fmt-newline { @@ -252,7 +246,7 @@ a.test-arrow:hover{ color: #999; } -:target > code { +:target > code, :target > .in-band { background-color: #494a3d; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 2b04dd2388d45..d20fea666e61d 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -84,12 +84,6 @@ pre { border-bottom-color: #ddd; } -:target { background: #FDFFD3; } - -:target > .in-band { - background: #FDFFD3; -} - .content .method .where, .content .fn .where, .content .where.fmt-newline { @@ -247,7 +241,7 @@ a.test-arrow:hover{ color: #999; } -:target > code { +:target > code, :target > .in-band { background: #FDFFD3; } From aa1ce32b105ff506257019a22684a98b61ab166a Mon Sep 17 00:00:00 2001 From: mark Date: Tue, 15 Jan 2019 16:40:10 -0600 Subject: [PATCH 21/34] update test output --- src/test/ui/issues/issue-5067.stderr | 72 +++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/src/test/ui/issues/issue-5067.stderr b/src/test/ui/issues/issue-5067.stderr index 433b7c8c04907..7ffc6071407c5 100644 --- a/src/test/ui/issues/issue-5067.stderr +++ b/src/test/ui/issues/issue-5067.stderr @@ -1,62 +1,110 @@ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:4:8 + --> $DIR/issue-5067.rs:9:8 | LL | ( $()* ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:6:8 + --> $DIR/issue-5067.rs:11:8 | LL | ( $()+ ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:12:9 + --> $DIR/issue-5067.rs:13:8 + | +LL | ( $()? ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:18:9 | LL | ( [$()*] ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:14:9 + --> $DIR/issue-5067.rs:20:9 | LL | ( [$()+] ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:20:8 + --> $DIR/issue-5067.rs:22:9 + | +LL | ( [$()?] ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:27:8 | LL | ( $($()* $(),* $(a)* $(a),* )* ) => {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:22:8 + --> $DIR/issue-5067.rs:29:8 | LL | ( $($()* $(),* $(a)* $(a),* )+ ) => {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:28:12 + --> $DIR/issue-5067.rs:31:8 + | +LL | ( $($()* $(),* $(a)* $(a),* )? ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:33:8 + | +LL | ( $($()? $(),* $(a)? $(a),* )* ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:35:8 + | +LL | ( $($()? $(),* $(a)? $(a),* )+ ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:37:8 + | +LL | ( $($()? $(),* $(a)? $(a),* )? ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:47:12 | LL | ( $(a $()+)* ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:30:12 + --> $DIR/issue-5067.rs:49:12 | LL | ( $(a $()*)+ ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:38:18 + --> $DIR/issue-5067.rs:51:12 + | +LL | ( $(a $()+)? ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:53:12 + | +LL | ( $(a $()?)+ ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:60:18 | LL | (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]); | ^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:50:8 + --> $DIR/issue-5067.rs:71:8 | -LL | ( $()* ) => {} +LL | ( $()* ) => {}; | ^^ -error: aborting due to 10 previous errors +error: aborting due to 18 previous errors From 32b28340b20ea8b45d3e663dc81bb9092ecdeeb1 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Tue, 15 Jan 2019 21:21:24 -0500 Subject: [PATCH 22/34] demonstrate symmetry --- src/libcore/cmp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 65792607a2824..a2f719cf406fe 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -170,7 +170,7 @@ use self::Ordering::*; /// let b2 = Book { isbn: 3, format: BookFormat::Ebook }; /// /// assert!(b1 == BookFormat::Paperback); -/// assert!(b1 != BookFormat::Ebook); +/// assert!(BookFormat::Ebook != b1); /// assert!(b1 == b2); /// ``` /// From bd8ee511a53547851a251c0e4b490cd381e970e8 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 15 Jan 2019 18:46:09 -0800 Subject: [PATCH 23/34] Add some links in std::fs. A few items were referenced, but did not have links. --- src/libstd/fs.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 119b3f7f9f296..3538816c1124c 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1121,7 +1121,9 @@ impl Permissions { /// writing. /// /// This operation does **not** modify the filesystem. To modify the - /// filesystem use the `fs::set_permissions` function. + /// filesystem use the [`fs::set_permissions`] function. + /// + /// [`fs::set_permissions`]: fn.set_permissions.html /// /// # Examples /// @@ -1639,10 +1641,15 @@ pub fn hard_link, Q: AsRef>(src: P, dst: Q) -> io::Result<( /// /// The `dst` path will be a symbolic link pointing to the `src` path. /// On Windows, this will be a file symlink, not a directory symlink; -/// for this reason, the platform-specific `std::os::unix::fs::symlink` -/// and `std::os::windows::fs::{symlink_file, symlink_dir}` should be +/// for this reason, the platform-specific [`std::os::unix::fs::symlink`] +/// and [`std::os::windows::fs::symlink_file`] or [`symlink_dir`] should be /// used instead to make the intent explicit. /// +/// [`std::os::unix::fs::symlink`]: ../os/unix/fs/fn.symlink.html +/// [`std::os::windows::fs::symlink_file`]: ../os/windows/fs/fn.symlink_file.html +/// [`symlink_dir`]: ../os/windows/fs/fn.symlink_dir.html +/// +/// /// # Examples /// /// ```no_run @@ -1795,7 +1802,7 @@ pub fn create_dir>(path: P) -> io::Result<()> { /// * If any directory in the path specified by `path` /// does not already exist and it could not be created otherwise. The specific /// error conditions for when a directory is being created (after it is -/// determined to not exist) are outlined by `fs::create_dir`. +/// determined to not exist) are outlined by [`fs::create_dir`]. /// /// Notable exception is made for situations where any of the directories /// specified in the `path` could not be created as it was being created concurrently. @@ -1803,6 +1810,8 @@ pub fn create_dir>(path: P) -> io::Result<()> { /// concurrently from multiple threads or processes is guaranteed not to fail /// due to a race condition with itself. /// +/// [`fs::create_dir`]: fn.create_dir.html +/// /// # Examples /// /// ```no_run @@ -1868,7 +1877,10 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// /// # Errors /// -/// See `file::remove_file` and `fs::remove_dir`. +/// See [`fs::remove_file`] and [`fs::remove_dir`]. +/// +/// [`fs::remove_file`]: fn.remove_file.html +/// [`fs::remove_dir`]: fn.remove_dir.html /// /// # Examples /// From ae4b14e837b613febc9a7ccfee4230fb22044a10 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 16 Jan 2019 13:51:24 +1100 Subject: [PATCH 24/34] Use `Lit` rather than `P` in `hir::ExprKind`. It's simpler and makes some benchmark run up to 1% faster. It also makes `hir::ExprKind` more like `ast::ExprKind` (which underwent the equivalent change in #55777). --- src/librustc/hir/lowering.rs | 2 +- src/librustc/hir/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 8badcbfc1b301..8cdc493e6fda7 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3775,7 +3775,7 @@ impl<'a> LoweringContext<'a> { let ohs = P(self.lower_expr(ohs)); hir::ExprKind::Unary(op, ohs) } - ExprKind::Lit(ref l) => hir::ExprKind::Lit(P((*l).clone())), + ExprKind::Lit(ref l) => hir::ExprKind::Lit((*l).clone()), ExprKind::Cast(ref expr, ref ty) => { let expr = P(self.lower_expr(expr)); hir::ExprKind::Cast(expr, self.lower_ty(ty, ImplTraitContext::disallowed())) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index fc4bd05476f6c..cf4bd27a0900a 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1466,7 +1466,7 @@ pub enum ExprKind { /// A unary operation (For example: `!x`, `*x`) Unary(UnOp, P), /// A literal (For example: `1`, `"foo"`) - Lit(P), + Lit(Lit), /// A cast (`foo as f64`) Cast(P, P), Type(P, P), From dc455286205bc0b3be6a6c6dcefff0498a6f4bcf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 16 Jan 2019 16:20:32 +1100 Subject: [PATCH 25/34] Remove `hir::Label`. It's identical to `ast::Label`. --- src/librustc/hir/mod.rs | 13 +------------ src/librustc/ich/impls_hir.rs | 2 +- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index cf4bd27a0900a..aaef1c722be96 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -19,7 +19,7 @@ use syntax_pos::{Span, DUMMY_SP, symbol::InternedString}; use syntax::source_map::{self, Spanned}; use rustc_target::spec::abi::Abi; use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect}; -use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy}; +use syntax::ast::{Attribute, Label, Lit, StrStyle, FloatTy, IntTy, UintTy}; use syntax::attr::InlineAttr; use syntax::ext::hygiene::SyntaxContext; use syntax::ptr::P; @@ -142,17 +142,6 @@ pub const DUMMY_HIR_ID: HirId = HirId { pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX; -#[derive(Clone, RustcEncodable, RustcDecodable, Copy)] -pub struct Label { - pub ident: Ident, -} - -impl fmt::Debug for Label { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "label({:?})", self.ident) - } -} - #[derive(Clone, RustcEncodable, RustcDecodable, Copy)] pub struct Lifetime { pub id: NodeId, diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 8ff60e5f56225..f48059b328ff3 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -153,7 +153,7 @@ impl_stable_hash_for!(enum hir::LifetimeName { Error, }); -impl_stable_hash_for!(struct hir::Label { +impl_stable_hash_for!(struct ast::Label { ident }); From 0772dbbb09bb28602756c964188563c64e78bc9c Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Wed, 16 Jan 2019 11:36:38 +0530 Subject: [PATCH 26/34] Fix release manifest generation --- src/tools/build-manifest/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 8c1baa55bcdca..4ca285b9b1db1 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -95,6 +95,7 @@ static TARGETS: &'static [&'static str] = &[ "wasm32-unknown-unknown", "x86_64-apple-darwin", "x86_64-apple-ios", + "x86_64-fortanix-unknown-sgx", "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-gnu", From 01d0ae96188b99c367178a38906b7269e1ada244 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Jan 2019 23:23:30 +0300 Subject: [PATCH 27/34] Prioritize variants as inherent associated items during name resolution --- src/librustc/lint/builtin.rs | 7 + src/librustc_lint/lib.rs | 5 + src/librustc_typeck/astconv.rs | 162 +++++++++++------- src/librustc_typeck/check/method/mod.rs | 61 +++---- src/librustc_typeck/check/mod.rs | 4 +- .../ui/type-alias-enum-variants-priority-2.rs | 13 ++ ...type-alias-enum-variants-priority-2.stderr | 12 ++ .../ui/type-alias-enum-variants-priority-3.rs | 10 ++ ...type-alias-enum-variants-priority-3.stderr | 8 + .../ui/type-alias-enum-variants-priority.rs | 20 +++ .../type-alias-enum-variants-priority.stderr | 26 +++ 11 files changed, 225 insertions(+), 103 deletions(-) create mode 100644 src/test/ui/type-alias-enum-variants-priority-2.rs create mode 100644 src/test/ui/type-alias-enum-variants-priority-2.stderr create mode 100644 src/test/ui/type-alias-enum-variants-priority-3.rs create mode 100644 src/test/ui/type-alias-enum-variants-priority-3.stderr create mode 100644 src/test/ui/type-alias-enum-variants-priority.rs create mode 100644 src/test/ui/type-alias-enum-variants-priority.stderr diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index c8d137a42b2e8..a0bd4f01cd231 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -368,6 +368,12 @@ declare_lint! { report_in_external_macro: true } +declare_lint! { + pub AMBIGUOUS_ASSOCIATED_ITEMS, + Warn, + "ambiguous associated items" +} + /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. #[derive(Copy, Clone)] @@ -433,6 +439,7 @@ impl LintPass for HardwiredLints { parser::QUESTION_MARK_MACRO_SEP, parser::ILL_FORMED_ATTRIBUTE_INPUT, DEPRECATED_IN_FUTURE, + AMBIGUOUS_ASSOCIATED_ITEMS, ) } } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 2d764d11c66aa..71c859d8dbea7 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -341,6 +341,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { reference: "issue #57571 ", edition: None, }, + FutureIncompatibleInfo { + id: LintId::of(AMBIGUOUS_ASSOCIATED_ITEMS), + reference: "issue #57644 ", + edition: None, + }, ]); // Register renamed and removed lints. diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8e5eaa18b9de0..534279e981d62 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -10,6 +10,7 @@ use hir::HirVec; use lint; use middle::resolve_lifetime as rl; use namespace::Namespace; +use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; @@ -1278,29 +1279,50 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } // Create a type from a path to an associated type. - // For a path `A::B::C::D`, `ty` and `ty_path_def` are the type and def for `A::B::C` + // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C` // and item_segment is the path segment for `D`. We return a type and a def for // the whole path. - // Will fail except for `T::A` and `Self::A`; i.e., if `ty`/`ty_path_def` are not a type + // Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type // parameter or `Self`. - pub fn associated_path_def_to_ty(&self, - ref_id: ast::NodeId, - span: Span, - ty: Ty<'tcx>, - ty_path_def: Def, - item_segment: &hir::PathSegment) - -> (Ty<'tcx>, Def) - { + pub fn associated_path_to_ty( + &self, + ref_id: ast::NodeId, + span: Span, + qself_ty: Ty<'tcx>, + qself_def: Def, + assoc_segment: &hir::PathSegment, + permit_variants: bool, + ) -> (Ty<'tcx>, Def) { let tcx = self.tcx(); - let assoc_name = item_segment.ident; + let assoc_ident = assoc_segment.ident; - debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name); + debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident); - self.prohibit_generics(slice::from_ref(item_segment)); + self.prohibit_generics(slice::from_ref(assoc_segment)); + + // Check if we have an enum variant. + let mut variant_resolution = None; + if let ty::Adt(adt_def, _) = qself_ty.sty { + if adt_def.is_enum() { + let variant_def = adt_def.variants.iter().find(|vd| { + tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did) + }); + if let Some(variant_def) = variant_def { + let def = Def::Variant(variant_def.did); + if permit_variants { + check_type_alias_enum_variants_enabled(tcx, span); + tcx.check_stability(variant_def.did, Some(ref_id), span); + return (qself_ty, def); + } else { + variant_resolution = Some(def); + } + } + } + } // Find the type of the associated item, and the trait where the associated // item is declared. - let bound = match (&ty.sty, ty_path_def) { + let bound = match (&qself_ty.sty, qself_def) { (_, Def::SelfTy(Some(_), Some(impl_def_id))) => { // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. @@ -1313,77 +1335,61 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { }; let candidates = traits::supertraits(tcx, ty::Binder::bind(trait_ref)) - .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name)); + .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_ident)); - match self.one_bound_for_assoc_type(candidates, "Self", assoc_name, span) { + match self.one_bound_for_assoc_type(candidates, "Self", assoc_ident, span) { Ok(bound) => bound, Err(ErrorReported) => return (tcx.types.err, Def::Err), } } (&ty::Param(_), Def::SelfTy(Some(param_did), None)) | (&ty::Param(_), Def::TyParam(param_did)) => { - match self.find_bound_for_assoc_item(param_did, assoc_name, span) { + match self.find_bound_for_assoc_item(param_did, assoc_ident, span) { Ok(bound) => bound, 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.ident.name); - if let Some(suggested_name) = find_best_match_for_name( - input, - &assoc_name.as_str(), - None, - ) { - err.span_suggestion_with_applicability( + _ => { + if variant_resolution.is_some() { + // Variant in type position + let msg = format!("expected type, found variant `{}`", assoc_ident); + tcx.sess.span_err(span, &msg); + } else if qself_ty.is_enum() { + // Report as incorrect enum variant rather than ambiguous type. + let mut err = tcx.sess.struct_span_err( span, - "did you mean", - format!("{}::{}", ty_str, suggested_name.to_string()), - Applicability::MaybeIncorrect, + &format!("no variant `{}` on enum `{}`", &assoc_ident.as_str(), qself_ty), ); - } else { - err.span_label(span, "unknown variant"); - } - err.emit(); - return (tcx.types.err, Def::Err); - } - _ => { - // Check if we have an enum variant. - match ty.sty { - ty::Adt(adt_def, _) if adt_def.is_enum() => { - let variant_def = adt_def.variants.iter().find(|vd| { - tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did) - }); - if let Some(variant_def) = variant_def { - check_type_alias_enum_variants_enabled(tcx, span); - - let def = Def::Variant(variant_def.did); - tcx.check_stability(def.def_id(), Some(ref_id), span); - return (ty, def); - } - }, - _ => (), - } - - // Don't print `TyErr` to the user. - if !ty.references_error() { + // Check if it was a typo. + let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT"); + if let Some(suggested_name) = find_best_match_for_name( + adt_def.variants.iter().map(|variant| &variant.ident.name), + &assoc_ident.as_str(), + None, + ) { + err.span_suggestion_with_applicability( + span, + "did you mean", + format!("{}::{}", qself_ty, suggested_name), + Applicability::MaybeIncorrect, + ); + } else { + err.span_label(span, "unknown variant"); + } + err.emit(); + } else if !qself_ty.references_error() { + // Don't print `TyErr` to the user. self.report_ambiguous_associated_type(span, - &ty.to_string(), + &qself_ty.to_string(), "Trait", - &assoc_name.as_str()); + &assoc_ident.as_str()); } return (tcx.types.err, Def::Err); } }; let trait_did = bound.def_id(); - let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_name, trait_did, ref_id); + let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_ident, trait_did, ref_id); let item = tcx.associated_items(trait_did).find(|i| { Namespace::from(i.kind) == Namespace::Type && i.ident.modern() == assoc_ident @@ -1394,11 +1400,35 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let def = Def::AssociatedTy(item.def_id); if !item.vis.is_accessible_from(def_scope, tcx) { - let msg = format!("{} `{}` is private", def.kind_name(), assoc_name); + let msg = format!("{} `{}` is private", def.kind_name(), assoc_ident); tcx.sess.span_err(span, &msg); } tcx.check_stability(item.def_id, Some(ref_id), span); + if let Some(variant_def) = variant_resolution { + let mut err = tcx.struct_span_lint_node( + AMBIGUOUS_ASSOCIATED_ITEMS, + ref_id, + span, + "ambiguous associated item", + ); + + let mut could_refer_to = |def: Def, also| { + let note_msg = format!("`{}` could{} refer to {} defined here", + assoc_ident, also, def.kind_name()); + err.span_note(tcx.def_span(def.def_id()), ¬e_msg); + }; + could_refer_to(variant_def, ""); + could_refer_to(def, " also"); + + err.span_suggestion_with_applicability( + span, + "use fully-qualified syntax", + format!("<{} as {}>::{}", qself_ty, "Trait", assoc_ident), + Applicability::HasPlaceholders, + ).emit(); + } + (ty, def) } @@ -1773,7 +1803,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } else { Def::Err }; - self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0 + self.associated_path_to_ty(ast_ty.id, ast_ty.span, ty, def, segment, false).0 } hir::TyKind::Array(ref ty, ref length) => { let length_def_id = tcx.hir().local_def_id(length.id); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 02687df6a94fc..e71dc019471bd 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -408,45 +408,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tcx = self.tcx; - let mode = probe::Mode::Path; - match self.probe_for_name(span, mode, method_name, IsSuggestion(false), - self_ty, expr_id, ProbeScope::TraitsInScope) { - Ok(pick) => { - debug!("resolve_ufcs: pick={:?}", pick); - if let Some(import_id) = pick.import_id { - let import_def_id = tcx.hir().local_def_id(import_id); - debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); - Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) - .unwrap().insert(import_def_id); + // Check if we have an enum variant. + if let ty::Adt(adt_def, _) = self_ty.sty { + if adt_def.is_enum() { + let variant_def = adt_def.variants.iter().find(|vd| { + tcx.hygienic_eq(method_name, vd.ident, adt_def.did) + }); + if let Some(variant_def) = variant_def { + check_type_alias_enum_variants_enabled(tcx, span); + + let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); + tcx.check_stability(def.def_id(), Some(expr_id), span); + return Ok(def); } - - let def = pick.item.def(); - debug!("resolve_ufcs: def={:?}", def); - tcx.check_stability(def.def_id(), Some(expr_id), span); - - Ok(def) } - Err(err) => { - // Check if we have an enum variant. - match self_ty.sty { - ty::Adt(adt_def, _) if adt_def.is_enum() => { - let variant_def = adt_def.variants.iter().find(|vd| { - tcx.hygienic_eq(method_name, vd.ident, adt_def.did) - }); - if let Some(variant_def) = variant_def { - check_type_alias_enum_variants_enabled(tcx, span); - - let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); - tcx.check_stability(def.def_id(), Some(expr_id), span); - return Ok(def); - } - }, - _ => (), - } + } - Err(err) - } + let pick = self.probe_for_name(span, probe::Mode::Path, method_name, IsSuggestion(false), + self_ty, expr_id, ProbeScope::TraitsInScope)?; + debug!("resolve_ufcs: pick={:?}", pick); + if let Some(import_id) = pick.import_id { + let import_def_id = tcx.hir().local_def_id(import_id); + debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); + Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) + .unwrap().insert(import_def_id); } + + let def = pick.item.def(); + debug!("resolve_ufcs: def={:?}", def); + tcx.check_stability(def.def_id(), Some(expr_id), span); + Ok(def) } /// Find item with name `item_name` defined in impl/trait `def_id` diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1b07385d4d1f4..22300f2ae11ed 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4724,8 +4724,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { Def::Err }; - let (ty, def) = AstConv::associated_path_def_to_ty(self, node_id, path_span, - ty, def, segment); + let (ty, def) = AstConv::associated_path_to_ty(self, node_id, path_span, + ty, def, segment, true); // Write back the new resolution. let hir_id = self.tcx.hir().node_to_hir_id(node_id); diff --git a/src/test/ui/type-alias-enum-variants-priority-2.rs b/src/test/ui/type-alias-enum-variants-priority-2.rs new file mode 100644 index 0000000000000..295f8acf62f85 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority-2.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_enum_variants)] + +enum E { + V(u8) +} + +impl E { + fn V() {} +} + +fn main() { + ::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied +} diff --git a/src/test/ui/type-alias-enum-variants-priority-2.stderr b/src/test/ui/type-alias-enum-variants-priority-2.stderr new file mode 100644 index 0000000000000..c6ec96ebb7d3b --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority-2.stderr @@ -0,0 +1,12 @@ +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/type-alias-enum-variants-priority-2.rs:12:5 + | +LL | V(u8) + | ----- defined here +... +LL | ::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied + | ^^^^^^^^ expected 1 parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/type-alias-enum-variants-priority-3.rs b/src/test/ui/type-alias-enum-variants-priority-3.rs new file mode 100644 index 0000000000000..33f96553b57f0 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority-3.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_enum_variants)] + +enum E { + V +} + +fn check() -> ::V {} +//~^ ERROR expected type, found variant `V` + +fn main() {} diff --git a/src/test/ui/type-alias-enum-variants-priority-3.stderr b/src/test/ui/type-alias-enum-variants-priority-3.stderr new file mode 100644 index 0000000000000..b3451542a2570 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority-3.stderr @@ -0,0 +1,8 @@ +error: expected type, found variant `V` + --> $DIR/type-alias-enum-variants-priority-3.rs:7:15 + | +LL | fn check() -> ::V {} + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-enum-variants-priority.rs b/src/test/ui/type-alias-enum-variants-priority.rs new file mode 100644 index 0000000000000..db1da2b12e256 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_enum_variants)] +#![deny(ambiguous_associated_items)] + +enum E { + V +} + +trait Tr { + type V; + fn f() -> Self::V; +} + +impl Tr for E { + type V = u8; + fn f() -> Self::V { 0 } + //~^ ERROR ambiguous associated item + //~| WARN this was previously accepted +} + +fn main() {} diff --git a/src/test/ui/type-alias-enum-variants-priority.stderr b/src/test/ui/type-alias-enum-variants-priority.stderr new file mode 100644 index 0000000000000..dcf7dc77ed5ea --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority.stderr @@ -0,0 +1,26 @@ +error: ambiguous associated item + --> $DIR/type-alias-enum-variants-priority.rs:15:15 + | +LL | fn f() -> Self::V { 0 } + | ^^^^^^^ help: use fully-qualified syntax: `::V` + | +note: lint level defined here + --> $DIR/type-alias-enum-variants-priority.rs:2:9 + | +LL | #![deny(ambiguous_associated_items)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57644 +note: `V` could refer to variant defined here + --> $DIR/type-alias-enum-variants-priority.rs:5:5 + | +LL | V + | ^ +note: `V` could also refer to associated type defined here + --> $DIR/type-alias-enum-variants-priority.rs:9:5 + | +LL | type V; + | ^^^^^^^ + +error: aborting due to previous error + From e4e888534eae603dfd0d9f9e75e8bb21d5e35f06 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Thu, 17 Jan 2019 00:39:15 +0100 Subject: [PATCH 28/34] Document Unpin in std::prelude documentation --- src/libstd/prelude/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs index ec8318f3728eb..bf689bad559d3 100644 --- a/src/libstd/prelude/mod.rs +++ b/src/libstd/prelude/mod.rs @@ -44,8 +44,8 @@ //! The current version of the prelude (version 1) lives in //! [`std::prelude::v1`], and re-exports the following. //! -//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`]}. The marker -//! traits indicate fundamental properties of types. +//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`], [`Unpin`]}. The +//! marker traits indicate fundamental properties of types. //! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various //! operations for both destructors and overloading `()`. //! * [`std::mem`]::[`drop`][`mem::drop`], a convenience function for explicitly @@ -108,6 +108,7 @@ //! [`Sync`]: ../marker/trait.Sync.html //! [`ToOwned`]: ../borrow/trait.ToOwned.html //! [`ToString`]: ../string/trait.ToString.html +//! [`Unpin`]: ../marker/trait.Unpin.html //! [`Vec`]: ../vec/struct.Vec.html //! [`Clone::clone`]: ../clone/trait.Clone.html#tymethod.clone //! [`mem::drop`]: ../mem/fn.drop.html From 22251a87be74865cc977f3fdcc995c1c467361c7 Mon Sep 17 00:00:00 2001 From: Alexander Ronald Altman Date: Wed, 16 Jan 2019 20:10:18 -0600 Subject: [PATCH 29/34] Enhance `Pin` impl applicability for `PartialEq` and `PartialOrd`. --- src/libcore/pin.rs | 50 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 762e07549a52a..022481f463514 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -99,6 +99,7 @@ use fmt; use marker::{Sized, Unpin}; +use cmp::{self, PartialEq, PartialOrd}; use ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn}; /// A pinned pointer. @@ -112,16 +113,59 @@ use ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn}; /// [`Unpin`]: ../../std/marker/trait.Unpin.html /// [`pin` module]: ../../std/pin/index.html // -// Note: the derives below are allowed because they all only use `&P`, so they -// cannot move the value behind `pointer`. +// Note: the derives below, and the explicit `PartialEq` and `PartialOrd` +// implementations, are allowed because they all only use `&P`, so they cannot move +// the value behind `pointer`. #[stable(feature = "pin", since = "1.33.0")] #[fundamental] #[repr(transparent)] -#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Copy, Clone, Hash, Eq, Ord)] pub struct Pin

{ pointer: P, } +#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")] +impl PartialEq> for Pin

+where + P: PartialEq, +{ + + fn eq(&self, other: &Pin) -> bool { + self.pointer == other.pointer + } + + fn ne(&self, other: &Pin) -> bool { + self.pointer != other.pointer + } +} + +#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")] +impl PartialOrd> for Pin

+where + P: PartialOrd, +{ + + fn partial_cmp(&self, other: &Pin) -> Option { + self.pointer.partial_cmp(&other.pointer) + } + + fn lt(&self, other: &Pin) -> bool { + self.pointer < other.pointer + } + + fn le(&self, other: &Pin) -> bool { + self.pointer <= other.pointer + } + + fn gt(&self, other: &Pin) -> bool { + self.pointer > other.pointer + } + + fn ge(&self, other: &Pin) -> bool { + self.pointer >= other.pointer + } +} + impl Pin

where P::Target: Unpin, From 1e3f475d643603b9570710b13e20de587a22a5ea Mon Sep 17 00:00:00 2001 From: AB1908 Date: Thu, 17 Jan 2019 03:40:36 +0000 Subject: [PATCH 30/34] Add test for linking non-existent static library --- src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs | 6 ++++++ .../ui/feature-gate/feature-gate-static-nobundle-2.stderr | 7 +++++++ 2 files changed, 13 insertions(+) create mode 100644 src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs create mode 100644 src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs new file mode 100644 index 0000000000000..92844f9306d28 --- /dev/null +++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs @@ -0,0 +1,6 @@ +//~ ERROR kind="static-nobundle" is feature gated +// Test the behavior of rustc when non-existent library is statically linked + +// compile-flags: -l static-nobundle=nonexistent + +fn main() {} diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr new file mode 100644 index 0000000000000..419c21901a02f --- /dev/null +++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr @@ -0,0 +1,7 @@ +error[E0658]: kind="static-nobundle" is feature gated (see issue #37403) + | + = help: add #![feature(static_nobundle)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From fefe1dacb6255304dab5c13fb669b1d9d40f9e03 Mon Sep 17 00:00:00 2001 From: Alexander Ronald Altman Date: Wed, 16 Jan 2019 23:03:29 -0600 Subject: [PATCH 31/34] Fix tidy errors. --- src/libcore/pin.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 022481f463514..7c09a36d89883 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -129,7 +129,6 @@ impl PartialEq> for Pin

where P: PartialEq, { - fn eq(&self, other: &Pin) -> bool { self.pointer == other.pointer } @@ -144,7 +143,6 @@ impl PartialOrd> for Pin

where P: PartialOrd, { - fn partial_cmp(&self, other: &Pin) -> Option { self.pointer.partial_cmp(&other.pointer) } From 3884cc8df480eba9bb8d19fa46e9fe6c9f9d729b Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 17 Jan 2019 15:32:05 +0100 Subject: [PATCH 32/34] Fix typo bug in DepGraph::try_mark_green(). --- src/librustc/dep_graph/graph.rs | 2 +- .../incremental/change_name_of_static_in_fn.rs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/test/incremental/change_name_of_static_in_fn.rs diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 501ef01d74c6e..7384af108edbb 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -600,7 +600,7 @@ impl DepGraph { DepKind::Hir | DepKind::HirBody | DepKind::CrateMetadata => { - if dep_node.extract_def_id(tcx).is_none() { + if dep_dep_node.extract_def_id(tcx).is_none() { // If the node does not exist anymore, we // just fail to mark green. return None diff --git a/src/test/incremental/change_name_of_static_in_fn.rs b/src/test/incremental/change_name_of_static_in_fn.rs new file mode 100644 index 0000000000000..5b27b6808ead2 --- /dev/null +++ b/src/test/incremental/change_name_of_static_in_fn.rs @@ -0,0 +1,17 @@ + +// revisions:rpass1 rpass2 rpass3 + +// See issue #57692. + +#![allow(warnings)] + +fn main() { + #[cfg(rpass1)] + { + static map: u64 = 0; + } + #[cfg(not(rpass1))] + { + static MAP: u64 = 0; + } +} From e3ba6ed3f571119e2f9165805e77c20b5e7a14b4 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Thu, 17 Jan 2019 13:53:21 +0000 Subject: [PATCH 33/34] Fix suggestions given mulitple bad lifetimes When given multiple lifetimes prior to type parameters in generic parameters, do not ICE and print the correct suggestion. --- src/librustc_errors/lib.rs | 9 ++-- src/libsyntax/parse/parser.rs | 21 +++------ src/test/ui/lifetime-before-type-params.rs | 9 ++++ .../ui/lifetime-before-type-params.stderr | 47 +++++++++++++++++++ .../suggestions/suggest-move-lifetimes.stderr | 4 +- 5 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 src/test/ui/lifetime-before-type-params.rs create mode 100644 src/test/ui/lifetime-before-type-params.stderr diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index a074441f8a179..3e25f98ccd27c 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -135,10 +135,11 @@ impl CodeSuggestion { if let Some(line) = line_opt { if let Some(lo) = line.char_indices().map(|(i, _)| i).nth(lo) { let hi_opt = hi_opt.and_then(|hi| line.char_indices().map(|(i, _)| i).nth(hi)); - buf.push_str(match hi_opt { - Some(hi) => &line[lo..hi], - None => &line[lo..], - }); + match hi_opt { + Some(hi) if hi > lo => buf.push_str(&line[lo..hi]), + Some(_) => (), + None => buf.push_str(&line[lo..]), + } } if let None = hi_opt { buf.push('\n'); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 823c786bded26..5b430d13516b4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5234,22 +5234,13 @@ impl<'a> Parser<'a> { kind: ast::GenericParamKind::Lifetime, }); 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) - }; - bad_lifetime_pos.push(param_span); - - if let Ok(snippet) = self.sess.source_map().span_to_snippet(param_span) { + let remove_sp = last_comma_span.unwrap_or(self.prev_span).to(self.prev_span); + bad_lifetime_pos.push(self.prev_span); + if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.prev_span) { suggestions.push((remove_sp, String::new())); - suggestions.push((sp.shrink_to_lo(), format!("{}, ", snippet))); - } - if ate_comma { - last_comma_span = Some(self.prev_span); - continue + suggestions.push(( + sp.shrink_to_lo(), + format!("{}, ", snippet))); } } } else if self.check_ident() { diff --git a/src/test/ui/lifetime-before-type-params.rs b/src/test/ui/lifetime-before-type-params.rs new file mode 100644 index 0000000000000..9b905d4883a16 --- /dev/null +++ b/src/test/ui/lifetime-before-type-params.rs @@ -0,0 +1,9 @@ +#![allow(unused)] +fn first() {} +//~^ ERROR lifetime parameters must be declared prior to type parameters +fn second<'a, T, 'b>() {} +//~^ ERROR lifetime parameters must be declared prior to type parameters +fn third() {} +//~^ ERROR lifetime parameters must be declared prior to type parameters +fn fourth<'a, T, 'b, U, 'c, V>() {} +//~^ ERROR lifetime parameters must be declared prior to type parameters diff --git a/src/test/ui/lifetime-before-type-params.stderr b/src/test/ui/lifetime-before-type-params.stderr new file mode 100644 index 0000000000000..7ac8dffdfbe0c --- /dev/null +++ b/src/test/ui/lifetime-before-type-params.stderr @@ -0,0 +1,47 @@ +error: lifetime parameters must be declared prior to type parameters + --> $DIR/lifetime-before-type-params.rs:2:13 + | +LL | fn first() {} + | ^^ ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | fn first<'a, 'b, T>() {} + | ^^^ ^^^ -- + +error: lifetime parameters must be declared prior to type parameters + --> $DIR/lifetime-before-type-params.rs:4:18 + | +LL | fn second<'a, T, 'b>() {} + | ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | fn second<'a, 'b, T>() {} + | ^^^ -- + +error: lifetime parameters must be declared prior to type parameters + --> $DIR/lifetime-before-type-params.rs:6:16 + | +LL | fn third() {} + | ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | fn third<'a, T, U>() {} + | ^^^ -- + +error: lifetime parameters must be declared prior to type parameters + --> $DIR/lifetime-before-type-params.rs:8:18 + | +LL | fn fourth<'a, T, 'b, U, 'c, V>() {} + | ^^ ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | fn fourth<'a, 'b, 'c, T, U, V>() {} + | ^^^ ^^^ -- -- + +error[E0601]: `main` function not found in crate `lifetime_before_type_params` + | + = note: consider adding a `main` function to `$DIR/lifetime-before-type-params.rs` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr index 72a2cbe6bf6de..b36e927b5c0c6 100644 --- a/src/test/ui/suggestions/suggest-move-lifetimes.stderr +++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr @@ -16,7 +16,7 @@ LL | struct B { //~ ERROR lifetime parameters must be declared help: move the lifetime parameter prior to the first type parameter | LL | struct B<'a, T, U> { //~ ERROR lifetime parameters must be declared - | ^^^ -- + | ^^^ -- error: lifetime parameters must be declared prior to type parameters --> $DIR/suggest-move-lifetimes.rs:10:16 @@ -36,7 +36,7 @@ LL | struct D { //~ ERROR lifetime parameters must be decla help: move the lifetime parameter prior to the first type parameter | LL | struct D<'a, 'b, 'c, T, U, V> { //~ ERROR lifetime parameters must be declared - | ^^^ ^^^ ^^^ --- + | ^^^ ^^^ ^^^ -- -- error: aborting due to 4 previous errors From ec3c5b0199045b3ae3959631998451543bd99518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 17 Jan 2019 21:19:30 -0800 Subject: [PATCH 34/34] Use structured suggestion to surround struct literal with parenthesis --- src/librustc_resolve/lib.rs | 42 ++++++++++++++++++++++++---- src/test/ui/error-codes/E0423.stderr | 12 ++++++-- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 39be3cb744080..430edcafae26a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3369,6 +3369,29 @@ impl<'a> Resolver<'a> { Ok(ref snippet) if snippet == "{" => true, _ => false, }; + // In case this could be a struct literal that needs to be surrounded + // by parenthesis, find the appropriate span. + let mut i = 0; + let mut closing_brace = None; + loop { + sp = sm.next_point(sp); + match sm.span_to_snippet(sp) { + Ok(ref snippet) => { + if snippet == "}" { + let sp = span.to(sp); + if let Ok(snippet) = sm.span_to_snippet(sp) { + closing_brace = Some((sp, snippet)); + } + break; + } + } + _ => break, + } + i += 1; + if i > 100 { // The bigger the span the more likely we're + break; // incorrect. Bound it to 100 chars long. + } + } match source { PathSource::Expr(Some(parent)) => { match parent.node { @@ -3395,11 +3418,20 @@ impl<'a> Resolver<'a> { } }, PathSource::Expr(None) if followed_by_brace == true => { - err.span_label( - span, - format!("did you mean `({} {{ /* fields */ }})`?", - path_str), - ); + if let Some((sp, snippet)) = closing_brace { + err.span_suggestion_with_applicability( + sp, + "surround the struct literal with parenthesis", + format!("({})", snippet), + Applicability::MaybeIncorrect, + ); + } else { + err.span_label( + span, + format!("did you mean `({} {{ /* fields */ }})`?", + path_str), + ); + } return (err, candidates); }, _ => { diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr index df9ed631a1c2e..3f3c78c68d097 100644 --- a/src/test/ui/error-codes/E0423.stderr +++ b/src/test/ui/error-codes/E0423.stderr @@ -29,19 +29,25 @@ error[E0423]: expected value, found struct `S` --> $DIR/E0423.rs:12:32 | LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); } - | ^ did you mean `(S { /* fields */ })`? + | ^--------------- + | | + | help: surround the struct literal with parenthesis: `(S { x: 1, y: 2 })` error[E0423]: expected value, found struct `T` --> $DIR/E0423.rs:15:8 | LL | if T {} == T {} { println!("Ok"); } - | ^ did you mean `(T { /* fields */ })`? + | ^--- + | | + | help: surround the struct literal with parenthesis: `(T {})` error[E0423]: expected value, found struct `std::ops::Range` --> $DIR/E0423.rs:21:14 | LL | for _ in std::ops::Range { start: 0, end: 10 } {} - | ^^^^^^^^^^^^^^^ did you mean `(std::ops::Range { /* fields */ })`? + | ^^^^^^^^^^^^^^^---------------------- + | | + | help: surround the struct literal with parenthesis: `(std::ops::Range { start: 0, end: 10 })` error: aborting due to 7 previous errors