From 38de102cffb7692738ec7940794e59452372d395 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Wed, 20 Jul 2022 21:43:37 -0400 Subject: [PATCH 01/23] Support eager and lazy methods for providing references and values There are times where computing a value may be cheap, or where computing a reference may be expensive, so this fills out the possibilities. --- library/core/src/any.rs | 74 +++++++++++++++++++++++++++++++++++---- library/core/tests/any.rs | 2 +- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/library/core/src/any.rs b/library/core/src/any.rs index e54f6c912d594..3bfb675531e64 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -796,7 +796,7 @@ pub trait Provider { /// impl Provider for SomeConcreteType { /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { /// demand.provide_ref::(&self.field) - /// .provide_value::(|| self.num_field); + /// .provide_value::(self.num_field); /// } /// } /// ``` @@ -881,28 +881,55 @@ impl<'a> Demand<'a> { /// /// # Examples /// + /// Provides an `u8`. + /// + /// ```rust + /// #![feature(provide_any)] + /// + /// use std::any::{Provider, Demand}; + /// # struct SomeConcreteType { field: u8 } + /// + /// impl Provider for SomeConcreteType { + /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + /// demand.provide_value::(self.field); + /// } + /// } + /// ``` + #[unstable(feature = "provide_any", issue = "96024")] + pub fn provide_value(&mut self, value: T) -> &mut Self + where + T: 'static, + { + self.provide::>(value) + } + + /// Provide a value or other type with only static lifetimes computed using a closure. + /// + /// # Examples + /// /// Provides a `String` by cloning. /// /// ```rust - /// # #![feature(provide_any)] + /// #![feature(provide_any)] + /// /// use std::any::{Provider, Demand}; /// # struct SomeConcreteType { field: String } /// /// impl Provider for SomeConcreteType { /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - /// demand.provide_value::(|| self.field.clone()); + /// demand.provide_value_with::(|| self.field.clone()); /// } /// } /// ``` #[unstable(feature = "provide_any", issue = "96024")] - pub fn provide_value(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self + pub fn provide_value_with(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self where T: 'static, { self.provide_with::>(fulfil) } - /// Provide a reference, note that the referee type must be bounded by `'static`, + /// Provide a reference. The referee type must be bounded by `'static`, /// but may be unsized. /// /// # Examples @@ -910,7 +937,8 @@ impl<'a> Demand<'a> { /// Provides a reference to a field as a `&str`. /// /// ```rust - /// # #![feature(provide_any)] + /// #![feature(provide_any)] + /// /// use std::any::{Provider, Demand}; /// # struct SomeConcreteType { field: String } /// @@ -925,6 +953,40 @@ impl<'a> Demand<'a> { self.provide::>>(value) } + /// Provide a reference computed using a closure. The referee type + /// must be bounded by `'static`, but may be unsized. + /// + /// # Examples + /// + /// Provides a reference to a field as a `&str`. + /// + /// ```rust + /// #![feature(provide_any)] + /// + /// use std::any::{Provider, Demand}; + /// # struct SomeConcreteType { business: String, party: String } + /// # fn today_is_a_weekday() -> bool { true } + /// + /// impl Provider for SomeConcreteType { + /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + /// demand.provide_ref_with::(|| { + /// if today_is_a_weekday() { + /// &self.business + /// } else { + /// &self.party + /// } + /// }); + /// } + /// } + /// ``` + #[unstable(feature = "provide_any", issue = "96024")] + pub fn provide_ref_with( + &mut self, + fulfil: impl FnOnce() -> &'a T, + ) -> &mut Self { + self.provide_with::>>(fulfil) + } + /// Provide a value with the given `Type` tag. fn provide(&mut self, value: I::Reified) -> &mut Self where diff --git a/library/core/tests/any.rs b/library/core/tests/any.rs index 8ed0c88808fe2..9538b81394957 100644 --- a/library/core/tests/any.rs +++ b/library/core/tests/any.rs @@ -142,7 +142,7 @@ impl Provider for SomeConcreteType { demand .provide_ref::(&self.some_string) .provide_ref::(&self.some_string) - .provide_value::(|| "bye".to_owned()); + .provide_value_with::(|| "bye".to_owned()); } } From 260ec9347838714ad9fa4f7e083bdc0448f4f9be Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 21 Jul 2022 21:39:20 -0400 Subject: [PATCH 02/23] Add `Provider::{would_be_satisfied_by_value_of,would_be_satisfied_by_ref_of}` While the `provide_*` methods already short-circuit when a value has been provided, there are times where an expensive computation is needed to determine if the `provide_*` method can even be called. --- library/core/src/any.rs | 165 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 3bfb675531e64..1a379ecc11c01 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -1008,6 +1008,156 @@ impl<'a> Demand<'a> { } self } + + /// Check if the `Demand` would be satisfied if provided with a + /// value of the specified type. If the type does not match or has + /// already been provided, returns false. + /// + /// # Examples + /// + /// Check if an `u8` still needs to be provided and then provides + /// it. + /// + /// ```rust + /// #![feature(provide_any)] + /// + /// use std::any::{Provider, Demand}; + /// + /// struct Parent(Option); + /// + /// impl Provider for Parent { + /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + /// if let Some(v) = self.0 { + /// demand.provide_value::(v); + /// } + /// } + /// } + /// + /// struct Child { + /// parent: Parent, + /// } + /// + /// impl Child { + /// // Pretend that this takes a lot of resources to evaluate. + /// fn an_expensive_computation(&self) -> Option { + /// Some(99) + /// } + /// } + /// + /// impl Provider for Child { + /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + /// // In general, we don't know if this call will provide + /// // an `u8` value or not... + /// self.parent.provide(demand); + /// + /// // ...so we check to see if the `u8` is needed before + /// // we run our expensive computation. + /// if demand.would_be_satisfied_by_value_of::() { + /// if let Some(v) = self.an_expensive_computation() { + /// demand.provide_value::(v); + /// } + /// } + /// + /// // The demand will be satisfied now, regardless of if + /// // the parent provided the value or we did. + /// assert!(!demand.would_be_satisfied_by_value_of::()); + /// } + /// } + /// + /// let parent = Parent(Some(42)); + /// let child = Child { parent }; + /// assert_eq!(Some(42), std::any::request_value::(&child)); + /// + /// let parent = Parent(None); + /// let child = Child { parent }; + /// assert_eq!(Some(99), std::any::request_value::(&child)); + /// ``` + #[unstable(feature = "provide_any", issue = "96024")] + pub fn would_be_satisfied_by_value_of(&self) -> bool + where + T: 'static, + { + self.would_be_satisfied_by::>() + } + + /// Check if the `Demand` would be satisfied if provided with a + /// reference to a value of the specified type. If the type does + /// not match or has already been provided, returns false. + /// + /// # Examples + /// + /// Check if a `&str` still needs to be provided and then provides + /// it. + /// + /// ```rust + /// #![feature(provide_any)] + /// + /// use std::any::{Provider, Demand}; + /// + /// struct Parent(Option); + /// + /// impl Provider for Parent { + /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + /// if let Some(v) = &self.0 { + /// demand.provide_ref::(v); + /// } + /// } + /// } + /// + /// struct Child { + /// parent: Parent, + /// name: String, + /// } + /// + /// impl Child { + /// // Pretend that this takes a lot of resources to evaluate. + /// fn an_expensive_computation(&self) -> Option<&str> { + /// Some(&self.name) + /// } + /// } + /// + /// impl Provider for Child { + /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + /// // In general, we don't know if this call will provide + /// // a `str` reference or not... + /// self.parent.provide(demand); + /// + /// // ...so we check to see if the `&str` is needed before + /// // we run our expensive computation. + /// if demand.would_be_satisfied_by_ref_of::() { + /// if let Some(v) = self.an_expensive_computation() { + /// demand.provide_ref::(v); + /// } + /// } + /// + /// // The demand will be satisfied now, regardless of if + /// // the parent provided the reference or we did. + /// assert!(!demand.would_be_satisfied_by_ref_of::()); + /// } + /// } + /// + /// let parent = Parent(Some("parent".into())); + /// let child = Child { parent, name: "child".into() }; + /// assert_eq!(Some("parent"), std::any::request_ref::(&child)); + /// + /// let parent = Parent(None); + /// let child = Child { parent, name: "child".into() }; + /// assert_eq!(Some("child"), std::any::request_ref::(&child)); + /// ``` + #[unstable(feature = "provide_any", issue = "96024")] + pub fn would_be_satisfied_by_ref_of(&self) -> bool + where + T: ?Sized + 'static, + { + self.would_be_satisfied_by::>>() + } + + fn would_be_satisfied_by(&self) -> bool + where + I: tags::Type<'a>, + { + matches!(self.0.downcast::(), Some(TaggedOption(None))) + } } #[unstable(feature = "provide_any", issue = "96024")] @@ -1112,6 +1262,21 @@ impl<'a> dyn Erased<'a> + 'a { /// Returns some reference to the dynamic value if it is tagged with `I`, /// or `None` otherwise. #[inline] + fn downcast(&self) -> Option<&TaggedOption<'a, I>> + where + I: tags::Type<'a>, + { + if self.tag_id() == TypeId::of::() { + // SAFETY: Just checked whether we're pointing to an I. + Some(unsafe { &*(self as *const Self).cast::>() }) + } else { + None + } + } + + /// Returns some mutable reference to the dynamic value if it is tagged with `I`, + /// or `None` otherwise. + #[inline] fn downcast_mut(&mut self) -> Option<&mut TaggedOption<'a, I>> where I: tags::Type<'a>, From 81a583c21e74d600ef8c4b45a3d5088382300e17 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 3 Aug 2022 22:24:47 +0200 Subject: [PATCH 03/23] Try normalizing types without RevealAll in ParamEnv in mir validation Before, the MIR validator used RevealAll in its ParamEnv for type checking. This could cause false negatives in some cases due to RevealAll ParamEnvs not always use all predicates as expected here. Since some MIR passes like inlining use RevealAll as well, keep using it in the MIR validator too, but when it fails usign RevealAll, also try the check without it, to stop false negatives. --- .../src/transform/validate.rs | 28 +++++++++++++------ src/test/ui/mir/issue-99866.rs | 25 +++++++++++++++++ 2 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/mir/issue-99866.rs diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 45a94972c1134..ddde9ff4c0281 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -181,16 +181,28 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if (src, dest).has_opaque_types() { return true; } + + let try_equal_with_param_env = |param_env| { + let src = self.tcx.normalize_erasing_regions(param_env, src); + let dest = self.tcx.normalize_erasing_regions(param_env, dest); + // Type-changing assignments can happen when subtyping is used. While + // all normal lifetimes are erased, higher-ranked types with their + // late-bound lifetimes are still around and can lead to type + // differences. So we compare ignoring lifetimes. + equal_up_to_regions(self.tcx, param_env, src, dest) + }; + // Normalize projections and things like that. + // First, try with reveal_all. This might not work in some cases, as the predicates + // can be cleared in reveal_all mode. We try the reveal first anyways as it is used + // by some other passes like inlining as well. let param_env = self.param_env.with_reveal_all_normalized(self.tcx); - let src = self.tcx.normalize_erasing_regions(param_env, src); - let dest = self.tcx.normalize_erasing_regions(param_env, dest); - - // Type-changing assignments can happen when subtyping is used. While - // all normal lifetimes are erased, higher-ranked types with their - // late-bound lifetimes are still around and can lead to type - // differences. So we compare ignoring lifetimes. - equal_up_to_regions(self.tcx, param_env, src, dest) + if try_equal_with_param_env(param_env) { + true + } else { + // If this fails, we can try it without the reveal. + try_equal_with_param_env(self.param_env) + } } } diff --git a/src/test/ui/mir/issue-99866.rs b/src/test/ui/mir/issue-99866.rs new file mode 100644 index 0000000000000..d39ae6ebf1da2 --- /dev/null +++ b/src/test/ui/mir/issue-99866.rs @@ -0,0 +1,25 @@ +// check-pass +pub trait Backend { + type DescriptorSetLayout; +} + +pub struct Back; + +impl Backend for Back { + type DescriptorSetLayout = u32; +} + +pub struct HalSetLayouts { + vertex_layout: ::DescriptorSetLayout, +} + +impl HalSetLayouts { + pub fn iter(self) -> DSL + where + Back: Backend, + { + self.vertex_layout + } +} + +fn main() {} From 96d4137deed6c52c6db2dd19568c37d1c160f1e7 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 6 Aug 2022 14:22:57 +0200 Subject: [PATCH 04/23] Only normalize once in mir validator typechecker Before, it called `normalize_erasing_regions` twice since `equal_up_to_regions` called it as well for both types. --- .../src/transform/validate.rs | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index ddde9ff4c0281..69113e57bdc5b 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -182,27 +182,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { return true; } - let try_equal_with_param_env = |param_env| { - let src = self.tcx.normalize_erasing_regions(param_env, src); - let dest = self.tcx.normalize_erasing_regions(param_env, dest); - // Type-changing assignments can happen when subtyping is used. While - // all normal lifetimes are erased, higher-ranked types with their - // late-bound lifetimes are still around and can lead to type - // differences. So we compare ignoring lifetimes. - equal_up_to_regions(self.tcx, param_env, src, dest) - }; - // Normalize projections and things like that. + // Type-changing assignments can happen when subtyping is used. While + // all normal lifetimes are erased, higher-ranked types with their + // late-bound lifetimes are still around and can lead to type + // differences. So we compare ignoring lifetimes. + // First, try with reveal_all. This might not work in some cases, as the predicates // can be cleared in reveal_all mode. We try the reveal first anyways as it is used // by some other passes like inlining as well. let param_env = self.param_env.with_reveal_all_normalized(self.tcx); - if try_equal_with_param_env(param_env) { - true - } else { - // If this fails, we can try it without the reveal. - try_equal_with_param_env(self.param_env) + if equal_up_to_regions(self.tcx, param_env, src, dest) { + return true; } + + // If this fails, we can try it without the reveal. + equal_up_to_regions(self.tcx, self.param_env, src, dest) } } From c846a2af8ddaa14ff2c2da25bc97bbd8d4284df2 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 14 Jun 2022 10:44:14 -0700 Subject: [PATCH 05/23] Make `std::os::fd` public. `std::os::fd` defines types like `OwnedFd` and `RawFd` and is common between Unix and non-Unix platforms that share a basic file-descriptor concept. Rust currently uses this internally to simplify its own code, but it would be useful for external users in the same way, so make it public. This means that `OwnedFd` etc. will all appear in three places, for example on unix platforms: - `std::os::fd::OwnedFd` - `std::os::unix::io::OwnedFd` - `std::os::unix::prelude::OwnedFd` --- library/std/src/os/fd/mod.rs | 14 ++++++++++++-- library/std/src/os/fd/owned.rs | 5 +---- library/std/src/os/fd/raw.rs | 15 +++------------ library/std/src/os/mod.rs | 2 +- library/std/src/os/unix/io/fd.rs | 8 -------- library/std/src/os/unix/io/mod.rs | 11 +++++------ library/std/src/os/unix/io/raw.rs | 6 ------ library/std/src/os/unix/io/{fd => }/tests.rs | 0 library/std/src/os/wasi/io/mod.rs | 8 +------- 9 files changed, 23 insertions(+), 46 deletions(-) delete mode 100644 library/std/src/os/unix/io/fd.rs delete mode 100644 library/std/src/os/unix/io/raw.rs rename library/std/src/os/unix/io/{fd => }/tests.rs (100%) diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs index a456947534a45..8043d1a53d279 100644 --- a/library/std/src/os/fd/mod.rs +++ b/library/std/src/os/fd/mod.rs @@ -1,16 +1,26 @@ //! Owned and borrowed Unix-like file descriptors. +//! +//! This module is supported on Unix platforms, and also some non-Unix +//! platforms which use a similar file descriptor system for referencing OS +//! resources. #![stable(feature = "io_safety", since = "1.63.0")] #![deny(unsafe_op_in_unsafe_fn)] // `RawFd`, `AsRawFd`, etc. -pub mod raw; +mod raw; // `OwnedFd`, `AsFd`, etc. -pub mod owned; +mod owned; // Implementations for `AsRawFd` etc. for network types. mod net; #[cfg(test)] mod tests; + +// Export the types and traits for the public API. +#[stable(feature = "io_safety", since = "1.63.0")] +pub use owned::*; +#[stable(feature = "rust1", since = "1.0.0")] +pub use raw::*; diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index a463bc41db7aa..3a1b04a83fa79 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -205,10 +205,7 @@ pub trait AsFd { /// ```rust,no_run /// use std::fs::File; /// # use std::io; - /// # #[cfg(target_os = "wasi")] - /// # use std::os::wasi::io::{AsFd, BorrowedFd}; - /// # #[cfg(unix)] - /// # use std::os::unix::io::{AsFd, BorrowedFd}; + /// # use std::os::fd::{AsFd, BorrowedFd}; /// /// let mut f = File::open("foo.txt")?; /// # #[cfg(any(unix, target_os = "wasi"))] diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 1b3d110426feb..42a9effcf92ab 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -42,10 +42,7 @@ pub trait AsRawFd { /// ```no_run /// use std::fs::File; /// # use std::io; - /// #[cfg(unix)] - /// use std::os::unix::io::{AsRawFd, RawFd}; - /// #[cfg(target_os = "wasi")] - /// use std::os::wasi::io::{AsRawFd, RawFd}; + /// use std::os::fd::{AsRawFd, RawFd}; /// /// let mut f = File::open("foo.txt")?; /// // Note that `raw_fd` is only valid as long as `f` exists. @@ -83,10 +80,7 @@ pub trait FromRawFd { /// ```no_run /// use std::fs::File; /// # use std::io; - /// #[cfg(unix)] - /// use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd}; - /// #[cfg(target_os = "wasi")] - /// use std::os::wasi::io::{FromRawFd, IntoRawFd, RawFd}; + /// use std::os::fd::{FromRawFd, IntoRawFd, RawFd}; /// /// let f = File::open("foo.txt")?; /// # #[cfg(any(unix, target_os = "wasi"))] @@ -121,10 +115,7 @@ pub trait IntoRawFd { /// ```no_run /// use std::fs::File; /// # use std::io; - /// #[cfg(unix)] - /// use std::os::unix::io::{IntoRawFd, RawFd}; - /// #[cfg(target_os = "wasi")] - /// use std::os::wasi::io::{IntoRawFd, RawFd}; + /// use std::os::fd::{IntoRawFd, RawFd}; /// /// let f = File::open("foo.txt")?; /// #[cfg(any(unix, target_os = "wasi"))] diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 18c64b5100764..f62f5af774f0e 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -147,7 +147,7 @@ pub mod solid; pub mod vxworks; #[cfg(any(unix, target_os = "wasi", doc))] -mod fd; +pub mod fd; #[cfg(any(target_os = "linux", target_os = "android", doc))] mod net; diff --git a/library/std/src/os/unix/io/fd.rs b/library/std/src/os/unix/io/fd.rs deleted file mode 100644 index d4cb696459b7e..0000000000000 --- a/library/std/src/os/unix/io/fd.rs +++ /dev/null @@ -1,8 +0,0 @@ -//! Owned and borrowed file descriptors. - -// Tests for this module -#[cfg(test)] -mod tests; - -#[stable(feature = "io_safety", since = "1.63.0")] -pub use crate::os::fd::owned::*; diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 3ab5606f8897d..25b5dbff14f30 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -77,10 +77,9 @@ #![stable(feature = "rust1", since = "1.0.0")] -mod fd; -mod raw; - -#[stable(feature = "io_safety", since = "1.63.0")] -pub use fd::*; #[stable(feature = "rust1", since = "1.0.0")] -pub use raw::*; +pub use crate::os::fd::*; + +// Tests for this module +#[cfg(test)] +mod tests; diff --git a/library/std/src/os/unix/io/raw.rs b/library/std/src/os/unix/io/raw.rs deleted file mode 100644 index a4d2ba797d9c4..0000000000000 --- a/library/std/src/os/unix/io/raw.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! Unix-specific extensions to general I/O primitives. - -#![stable(feature = "rust1", since = "1.0.0")] - -#[stable(feature = "rust1", since = "1.0.0")] -pub use crate::os::fd::raw::*; diff --git a/library/std/src/os/unix/io/fd/tests.rs b/library/std/src/os/unix/io/tests.rs similarity index 100% rename from library/std/src/os/unix/io/fd/tests.rs rename to library/std/src/os/unix/io/tests.rs diff --git a/library/std/src/os/wasi/io/mod.rs b/library/std/src/os/wasi/io/mod.rs index 6c884e2eaf471..d528590d75b9a 100644 --- a/library/std/src/os/wasi/io/mod.rs +++ b/library/std/src/os/wasi/io/mod.rs @@ -1,12 +1,6 @@ //! WASI-specific extensions to general I/O primitives. -#![deny(unsafe_op_in_unsafe_fn)] #![unstable(feature = "wasi_ext", issue = "71213")] -mod fd; -mod raw; - -#[unstable(feature = "wasi_ext", issue = "71213")] -pub use fd::*; #[unstable(feature = "wasi_ext", issue = "71213")] -pub use raw::*; +pub use crate::os::fd::*; From 09bbc4224f36e05245e63d1766364ea821c83cd3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 21 Jun 2022 21:09:20 -0700 Subject: [PATCH 06/23] Update asrawfd.js. --- src/test/rustdoc-js-std/asrawfd.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/rustdoc-js-std/asrawfd.js b/src/test/rustdoc-js-std/asrawfd.js index fd228a59099e9..369a34f9c6eb7 100644 --- a/src/test/rustdoc-js-std/asrawfd.js +++ b/src/test/rustdoc-js-std/asrawfd.js @@ -6,9 +6,9 @@ const EXPECTED = { 'others': [ // Reproduction test for https://github.com/rust-lang/rust/issues/78724 // Validate that type alias methods get the correct path. - { 'path': 'std::os::unix::io::AsRawFd', 'name': 'as_raw_fd' }, - { 'path': 'std::os::wasi::io::AsRawFd', 'name': 'as_raw_fd' }, + { 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' }, + { 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' }, { 'path': 'std::os::linux::process::PidFd', 'name': 'as_raw_fd' }, - { 'path': 'std::os::unix::io::RawFd', 'name': 'as_raw_fd' }, + { 'path': 'std::os::fd::RawFd', 'name': 'as_raw_fd' }, ], }; From bda12629c3d0926c14b9fbe3f814972f8d50043c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 29 Jun 2022 19:07:43 -0700 Subject: [PATCH 07/23] Clarify that the `fd` module is supported on Unix and WASI. --- library/std/src/os/fd/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs index 8043d1a53d279..91dbe44878b1e 100644 --- a/library/std/src/os/fd/mod.rs +++ b/library/std/src/os/fd/mod.rs @@ -1,8 +1,7 @@ //! Owned and borrowed Unix-like file descriptors. //! -//! This module is supported on Unix platforms, and also some non-Unix -//! platforms which use a similar file descriptor system for referencing OS -//! resources. +//! This module is supported on Unix platforms and WASI, which both use a +//! similar file descriptor system for referencing OS resources. #![stable(feature = "io_safety", since = "1.63.0")] #![deny(unsafe_op_in_unsafe_fn)] From 7d80510c16bd2172427aff61e5d929aa695cdfa5 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 23 Aug 2022 11:57:13 -0700 Subject: [PATCH 08/23] Re-introduce `unstable` attributes. Add `#[unstable(feature = "os_fd", issue = "98699")]` to the new `pub use` declarations. --- library/std/src/os/fd/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs index 91dbe44878b1e..c6aa7c77dbc41 100644 --- a/library/std/src/os/fd/mod.rs +++ b/library/std/src/os/fd/mod.rs @@ -19,7 +19,7 @@ mod net; mod tests; // Export the types and traits for the public API. -#[stable(feature = "io_safety", since = "1.63.0")] +#[unstable(feature = "os_fd", issue = "98699")] pub use owned::*; -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "os_fd", issue = "98699")] pub use raw::*; From b9d3f654128ce6ba29e1e9ff31fcc44f2f04b59f Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Tue, 30 Aug 2022 15:17:45 -0700 Subject: [PATCH 09/23] [drop tracking] Use parent expression for scope Previously we were just using the parent node as the scope for a temporary value, but it turns out this is too narrow. For example, in an expression like Foo { b: &42, a: async { 0 }.await, } the scope for the &42 was set to the ExprField node for `b: &42`, when we actually want to use the Foo struct expression. We fix this by recursively searching through parent nodes until we find a Node::Expr. It may be that we don't find one, and if so that's okay, we will just fall back on the enclosing temporary scope which is always sufficient. --- .../src/check/generator_interior.rs | 17 +++++++++++++++-- .../drop_ranges/record_consumed_borrow.rs | 4 ++-- src/test/ui/async-await/issue-73137.rs | 3 +++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index 85a0d4e449906..f73d498aabc23 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -387,6 +387,18 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { ty.needs_drop(self.fcx.tcx, self.fcx.param_env) }; + let find_parent_expr = |mut hir_id| { + let hir = self.fcx.tcx.hir(); + hir_id = hir.find_parent_node(hir_id)?; + loop { + if let hir::Node::Expr(_) = self.fcx.tcx.hir().find(hir_id)? { + return Some(hir_id); + } else { + hir_id = hir.find_parent_node(hir_id)?; + } + } + }; + // Typically, the value produced by an expression is consumed by its parent in some way, // so we only have to check if the parent contains a yield (note that the parent may, for // example, store the value into a local variable, but then we already consider local @@ -409,8 +421,9 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { }) { self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id) } else { - debug!("parent_node: {:?}", self.fcx.tcx.hir().find_parent_node(expr.hir_id)); - match self.fcx.tcx.hir().find_parent_node(expr.hir_id) { + let parent_expr = find_parent_expr(expr.hir_id); + debug!("parent_expr: {:?}", parent_expr); + match parent_expr { Some(parent) => Some(Scope { id: parent.local_id, data: ScopeData::Node }), None => { self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id) diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs index ded0888c33e15..e22675e9d5f4e 100644 --- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs +++ b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs @@ -159,8 +159,8 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> { bk: rustc_middle::ty::BorrowKind, ) { debug!( - "borrow: place_with_id = {place_with_id:?}, diag_expr_id={diag_expr_id:?}, \ - borrow_kind={bk:?}" + "borrow: place_with_id = {place_with_id:#?}, diag_expr_id={diag_expr_id:#?}, \ + borrow_kind={bk:#?}" ); self.borrow_place(place_with_id); diff --git a/src/test/ui/async-await/issue-73137.rs b/src/test/ui/async-await/issue-73137.rs index c43ce2cadba04..dcbe7765a9e1c 100644 --- a/src/test/ui/async-await/issue-73137.rs +++ b/src/test/ui/async-await/issue-73137.rs @@ -2,6 +2,9 @@ // run-pass // edition:2018 +// revisions: normal drop-tracking +// [normal]compile-flags: -Zdrop-tracking=no +// [drop-tracking]compile-flags: -Zdrop-tracking #![allow(dead_code)] use std::future::Future; From 803e35abf7c2949fe04d1c403d69605f570d5637 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 31 Aug 2022 17:05:38 +0200 Subject: [PATCH 10/23] Remove unneeded extra whitespace before where clause --- src/librustdoc/html/format.rs | 13 ++++--------- src/librustdoc/html/render/mod.rs | 12 ++++++------ 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index b023792e95a58..05d10f8137fe8 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -349,8 +349,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( let where_preds = comma_sep(where_predicates, false); let clause = if f.alternate() { if ending == Ending::Newline { - // add a space so stripping
tags and breaking spaces still renders properly - format!(" where{where_preds}, ") + format!(" where{where_preds},") } else { format!(" where{where_preds}") } @@ -364,20 +363,16 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( if ending == Ending::Newline { let mut clause = " ".repeat(indent.saturating_sub(1)); - // add a space so stripping
tags and breaking spaces still renders properly - write!( - clause, - " where{where_preds}, " - )?; + write!(clause, "where{where_preds},")?; clause } else { // insert a
tag after a single space but before multiple spaces at the start if indent == 0 { - format!("
where{where_preds}") + format!("
where{where_preds}") } else { let mut clause = br_with_padding; clause.truncate(clause.len() - 5 * " ".len()); - write!(clause, " where{where_preds}")?; + write!(clause, "where{where_preds}")?; clause } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 6272f47f460ca..bff12e6fee9bd 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1739,8 +1739,8 @@ pub(crate) fn render_impl_summary( // in documentation pages for trait with automatic implementations like "Send" and "Sync". aliases: &[String], ) { - let id = - cx.derive_id(get_id_for_impl(&i.inner_impl().for_, i.inner_impl().trait_.as_ref(), cx)); + let inner_impl = i.inner_impl(); + let id = cx.derive_id(get_id_for_impl(&inner_impl.for_, inner_impl.trait_.as_ref(), cx)); let aliases = if aliases.is_empty() { String::new() } else { @@ -1752,9 +1752,9 @@ pub(crate) fn render_impl_summary( write!(w, "

"); if let Some(use_absolute) = use_absolute { - write!(w, "{}", i.inner_impl().print(use_absolute, cx)); + write!(w, "{}", inner_impl.print(use_absolute, cx)); if show_def_docs { - for it in &i.inner_impl().items { + for it in &inner_impl.items { if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind { w.write_str(" "); assoc_type( @@ -1772,11 +1772,11 @@ pub(crate) fn render_impl_summary( } } } else { - write!(w, "{}", i.inner_impl().print(false, cx)); + write!(w, "{}", inner_impl.print(false, cx)); } write!(w, "

"); - let is_trait = i.inner_impl().trait_.is_some(); + let is_trait = inner_impl.trait_.is_some(); if is_trait { if let Some(portability) = portability(&i.impl_item, Some(parent)) { write!(w, "{}", portability); From 4304d1d1e6ea31ca45b722047f516322af4305c4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 31 Aug 2022 17:05:46 +0200 Subject: [PATCH 11/23] Update rustdoc tests --- src/test/rustdoc-gui/src/lib2/lib.rs | 27 +++++++++++++++++++ .../const-generics/const-generics-docs.rs | 8 +++--- .../rustdoc/generic-associated-types/gats.rs | 4 +-- .../rustdoc/higher-ranked-trait-bounds.rs | 8 +++--- src/test/rustdoc/impl-parts.rs | 4 +-- src/test/rustdoc/issue-20727-4.rs | 4 +-- src/test/rustdoc/issue-21801.rs | 2 +- src/test/rustdoc/issue-29503.rs | 2 +- src/test/rustdoc/issue-34928.rs | 2 +- src/test/rustdoc/issue-50159.rs | 4 +-- src/test/rustdoc/issue-51236.rs | 2 +- src/test/rustdoc/issue-54705.rs | 6 ++--- src/test/rustdoc/issue-98697.rs | 2 +- .../rustdoc/primitive-slice-auto-trait.rs | 4 +-- src/test/rustdoc/synthetic_auto/basic.rs | 4 +-- src/test/rustdoc/synthetic_auto/complex.rs | 2 +- src/test/rustdoc/synthetic_auto/lifetimes.rs | 4 +-- src/test/rustdoc/synthetic_auto/manual.rs | 2 +- src/test/rustdoc/synthetic_auto/nested.rs | 4 +-- .../rustdoc/synthetic_auto/no-redundancy.rs | 2 +- src/test/rustdoc/synthetic_auto/project.rs | 4 +-- .../synthetic_auto/self-referential.rs | 2 +- .../rustdoc/synthetic_auto/static-region.rs | 2 +- src/test/rustdoc/where-clause-order.rs | 2 +- src/test/rustdoc/where.rs | 22 +++++++-------- 25 files changed, 77 insertions(+), 52 deletions(-) diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs index 87f91be3ac82c..7f3172878bfb5 100644 --- a/src/test/rustdoc-gui/src/lib2/lib.rs +++ b/src/test/rustdoc-gui/src/lib2/lib.rs @@ -143,3 +143,30 @@ pub struct LongItemInfo2; /// Some docs. #[doc(cfg(any(target_os = "android", target_os = "linux", target_os = "emscripten", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))] impl SimpleTrait for LongItemInfo2 {} + +pub struct WhereWhitespace; + +impl WhereWhitespace { + pub fn new(f: F) -> Self + where + F: FnMut() -> i32, + {} +} + +impl Whitespace<&K> for WhereWhitespace +where + K: std::fmt::Debug, +{ + type Output = WhereWhitespace; + fn index(&self, _key: &K) -> &Self::Output { + self + } +} + +pub trait Whitespace +where + Idx: ?Sized, +{ + type Output; + fn index(&self, index: Idx) -> &Self::Output; +} diff --git a/src/test/rustdoc/const-generics/const-generics-docs.rs b/src/test/rustdoc/const-generics/const-generics-docs.rs index 352a8e646bb49..87d2f29e26055 100644 --- a/src/test/rustdoc/const-generics/const-generics-docs.rs +++ b/src/test/rustdoc/const-generics/const-generics-docs.rs @@ -31,12 +31,12 @@ impl Trait<{1 + 2}> for u8 {} impl Trait for [u8; N] {} // @has foo/struct.Foo.html '//pre[@class="rust struct"]' \ -// 'pub struct Foo where u8: Trait' +// 'pub struct Foowhere u8: Trait' pub struct Foo where u8: Trait; // @has foo/struct.Bar.html '//pre[@class="rust struct"]' 'pub struct Bar(_)' pub struct Bar([T; N]); -// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header in-band"]' 'impl Foo where u8: Trait' +// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header in-band"]' 'impl Foowhere u8: Trait' impl Foo where u8: Trait { // @has - '//*[@id="associatedconstant.FOO_ASSOC"]' 'pub const FOO_ASSOC: usize' pub const FOO_ASSOC: usize = M + 13; @@ -50,14 +50,14 @@ impl Foo where u8: Trait { // @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8%2C%20M%3E"]/h3[@class="code-header in-band"]' 'impl Bar' impl Bar { // @has - '//*[@id="method.hey"]' \ - // 'pub fn hey(&self) -> Foo where u8: Trait' + // 'pub fn hey(&self) -> Foowhere u8: Trait' pub fn hey(&self) -> Foo where u8: Trait { Foo } } // @has foo/fn.test.html '//pre[@class="rust fn"]' \ -// 'pub fn test() -> impl Trait where u8: Trait' +// 'pub fn test() -> impl Traitwhere u8: Trait' pub fn test() -> impl Trait where u8: Trait { 2u8 } diff --git a/src/test/rustdoc/generic-associated-types/gats.rs b/src/test/rustdoc/generic-associated-types/gats.rs index ae981b9499a67..2b9d4952d04ee 100644 --- a/src/test/rustdoc/generic-associated-types/gats.rs +++ b/src/test/rustdoc/generic-associated-types/gats.rs @@ -3,7 +3,7 @@ // @has foo/trait.LendingIterator.html pub trait LendingIterator { - // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a" + // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item<'a>where Self: 'a" type Item<'a> where Self: 'a; // @has - '//*[@id="tymethod.next"]//h4[@class="code-header"]' \ @@ -24,7 +24,7 @@ impl LendingIterator for () { pub struct Infinite(T); // @has foo/trait.LendingIterator.html -// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a = &'a T" +// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a>where Self: 'a = &'a T" impl LendingIterator for Infinite { type Item<'a> where Self: 'a = &'a T; diff --git a/src/test/rustdoc/higher-ranked-trait-bounds.rs b/src/test/rustdoc/higher-ranked-trait-bounds.rs index b75b8de52f9cb..59b5b6e5797cc 100644 --- a/src/test/rustdoc/higher-ranked-trait-bounds.rs +++ b/src/test/rustdoc/higher-ranked-trait-bounds.rs @@ -4,7 +4,7 @@ pub trait Trait<'x> {} // @has foo/fn.test1.html -// @has - '//pre' "pub fn test1() where for<'a> &'a T: Iterator," +// @has - '//pre' "pub fn test1()where for<'a> &'a T: Iterator," pub fn test1() where for<'a> &'a T: Iterator, @@ -12,7 +12,7 @@ where } // @has foo/fn.test2.html -// @has - '//pre' "pub fn test2() where for<'a, 'b> &'a T: Trait<'b>," +// @has - '//pre' "pub fn test2()where for<'a, 'b> &'a T: Trait<'b>," pub fn test2() where for<'a, 'b> &'a T: Trait<'b>, @@ -20,7 +20,7 @@ where } // @has foo/fn.test3.html -// @has - '//pre' "pub fn test3() where F: for<'a, 'b> Fn(&'a u8, &'b u8)," +// @has - '//pre' "pub fn test3()where F: for<'a, 'b> Fn(&'a u8, &'b u8)," pub fn test3() where F: for<'a, 'b> Fn(&'a u8, &'b u8), @@ -38,7 +38,7 @@ pub struct Foo<'a> { // @has - '//span[@id="structfield.some_trait"]' "some_trait: &'a dyn for<'b> Trait<'b>" impl<'a> Foo<'a> { - // @has - '//h4[@class="code-header"]' "pub fn bar() where T: Trait<'a>," + // @has - '//h4[@class="code-header"]' "pub fn bar()where T: Trait<'a>," pub fn bar() where T: Trait<'a>, diff --git a/src/test/rustdoc/impl-parts.rs b/src/test/rustdoc/impl-parts.rs index 249158c1a1f89..b1481e1f27978 100644 --- a/src/test/rustdoc/impl-parts.rs +++ b/src/test/rustdoc/impl-parts.rs @@ -6,7 +6,7 @@ pub auto trait AnAutoTrait {} pub struct Foo { field: T } // @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl !AnAutoTrait for Foo where T: Sync," +// "impl !AnAutoTrait for Foowhere T: Sync," // @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ -// "impl !AnAutoTrait for Foo where T: Sync," +// "impl !AnAutoTrait for Foowhere T: Sync," impl !AnAutoTrait for Foo where T: Sync {} diff --git a/src/test/rustdoc/issue-20727-4.rs b/src/test/rustdoc/issue-20727-4.rs index 84fc6f94a265a..643f938759093 100644 --- a/src/test/rustdoc/issue-20727-4.rs +++ b/src/test/rustdoc/issue-20727-4.rs @@ -25,7 +25,7 @@ pub trait IndexMut: Index { pub mod reexport { // @has issue_20727_4/reexport/trait.Index.html - // @has - '//*[@class="rust trait"]' 'trait Index where Idx: ?Sized, {' + // @has - '//*[@class="rust trait"]' 'trait Indexwhere Idx: ?Sized,{' // @has - '//*[@class="rust trait"]' 'type Output: ?Sized' // @has - '//*[@class="rust trait"]' \ // 'fn index(&self, index: Idx) -> &Self::Output' @@ -33,7 +33,7 @@ pub mod reexport { // @has issue_20727_4/reexport/trait.IndexMut.html // @has - '//*[@class="rust trait"]' \ - // 'trait IndexMut: Index where Idx: ?Sized, {' + // 'trait IndexMut: Indexwhere Idx: ?Sized,{' // @has - '//*[@class="rust trait"]' \ // 'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;' pub use issue_20727::IndexMut; diff --git a/src/test/rustdoc/issue-21801.rs b/src/test/rustdoc/issue-21801.rs index 2a586b6ff6cdc..29d2ec64c206d 100644 --- a/src/test/rustdoc/issue-21801.rs +++ b/src/test/rustdoc/issue-21801.rs @@ -5,5 +5,5 @@ extern crate issue_21801; // @has issue_21801/struct.Foo.html // @has - '//*[@id="method.new"]' \ -// 'fn new(f: F) -> Foo where F: FnMut() -> i32' +// 'fn new(f: F) -> Foowhere F: FnMut() -> i32' pub use issue_21801::Foo; diff --git a/src/test/rustdoc/issue-29503.rs b/src/test/rustdoc/issue-29503.rs index 635c3175f8138..134821e1ef3ea 100644 --- a/src/test/rustdoc/issue-29503.rs +++ b/src/test/rustdoc/issue-29503.rs @@ -5,7 +5,7 @@ pub trait MyTrait { fn my_string(&self) -> String; } -// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header in-band']" "impl MyTrait for T where T: Debug" +// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header in-band']" "impl MyTrait for Twhere T: Debug" impl MyTrait for T where T: fmt::Debug, diff --git a/src/test/rustdoc/issue-34928.rs b/src/test/rustdoc/issue-34928.rs index 4184086f622ab..91b67757453d2 100644 --- a/src/test/rustdoc/issue-34928.rs +++ b/src/test/rustdoc/issue-34928.rs @@ -2,5 +2,5 @@ pub trait Bar {} -// @has foo/struct.Foo.html '//pre' 'pub struct Foo(pub T) where T: Bar;' +// @has foo/struct.Foo.html '//pre' 'pub struct Foo(pub T)where T: Bar;' pub struct Foo(pub T) where T: Bar; diff --git a/src/test/rustdoc/issue-50159.rs b/src/test/rustdoc/issue-50159.rs index d88c29217023a..43fb705f58994 100644 --- a/src/test/rustdoc/issue-50159.rs +++ b/src/test/rustdoc/issue-50159.rs @@ -11,8 +11,8 @@ impl Signal2 for B where B: Signal { } // @has issue_50159/struct.Switch.html -// @has - '//h3[@class="code-header in-band"]' 'impl Send for Switch where ::Item: Send' -// @has - '//h3[@class="code-header in-band"]' 'impl Sync for Switch where ::Item: Sync' +// @has - '//h3[@class="code-header in-band"]' 'impl Send for Switchwhere ::Item: Send' +// @has - '//h3[@class="code-header in-band"]' 'impl Sync for Switchwhere ::Item: Sync' // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 // @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5 pub struct Switch { diff --git a/src/test/rustdoc/issue-51236.rs b/src/test/rustdoc/issue-51236.rs index ee11ccc681163..aa5890a84514f 100644 --- a/src/test/rustdoc/issue-51236.rs +++ b/src/test/rustdoc/issue-51236.rs @@ -8,7 +8,7 @@ pub mod traits { // @has issue_51236/struct.Owned.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl Send for Owned where >::Reader: Send" +// "impl Send for Ownedwhere >::Reader: Send" pub struct Owned where T: for<'a> ::traits::Owned<'a> { marker: PhantomData<>::Reader>, } diff --git a/src/test/rustdoc/issue-54705.rs b/src/test/rustdoc/issue-54705.rs index bedaf5c4ddc36..ce0f85d25da56 100644 --- a/src/test/rustdoc/issue-54705.rs +++ b/src/test/rustdoc/issue-54705.rs @@ -1,13 +1,11 @@ pub trait ScopeHandle<'scope> {} - - // @has issue_54705/struct.ScopeFutureContents.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl<'scope, S> Send for ScopeFutureContents<'scope, S> where S: Sync" +// "impl<'scope, S> Send for ScopeFutureContents<'scope, S>where S: Sync" // // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl<'scope, S> Sync for ScopeFutureContents<'scope, S> where S: Sync" +// "impl<'scope, S> Sync for ScopeFutureContents<'scope, S>where S: Sync" pub struct ScopeFutureContents<'scope, S> where S: ScopeHandle<'scope>, { diff --git a/src/test/rustdoc/issue-98697.rs b/src/test/rustdoc/issue-98697.rs index 83e08094c0953..a8841f137fecf 100644 --- a/src/test/rustdoc/issue-98697.rs +++ b/src/test/rustdoc/issue-98697.rs @@ -8,7 +8,7 @@ extern crate issue_98697_reexport_with_anonymous_lifetime; -// @has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'fn repro() where F: Fn(&str)' +// @has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'fn repro()where F: Fn(&str)' // @!has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'for<' pub use issue_98697_reexport_with_anonymous_lifetime::repro; diff --git a/src/test/rustdoc/primitive-slice-auto-trait.rs b/src/test/rustdoc/primitive-slice-auto-trait.rs index b3f511bc1f153..7f8f74ff457a5 100644 --- a/src/test/rustdoc/primitive-slice-auto-trait.rs +++ b/src/test/rustdoc/primitive-slice-auto-trait.rs @@ -7,8 +7,8 @@ // @has - '//span[@class="in-band"]' 'Primitive Type slice' // @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations' -// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Send for [T] where T: Send' -// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Sync for [T] where T: Sync' +// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Send for [T]where T: Send' +// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Sync for [T]where T: Sync' #[doc(primitive = "slice")] /// this is a test! mod slice_prim {} diff --git a/src/test/rustdoc/synthetic_auto/basic.rs b/src/test/rustdoc/synthetic_auto/basic.rs index 54c54fdbf68a8..19138fd1aceb2 100644 --- a/src/test/rustdoc/synthetic_auto/basic.rs +++ b/src/test/rustdoc/synthetic_auto/basic.rs @@ -1,6 +1,6 @@ // @has basic/struct.Foo.html -// @has - '//h3[@class="code-header in-band"]' 'impl Send for Foo where T: Send' -// @has - '//h3[@class="code-header in-band"]' 'impl Sync for Foo where T: Sync' +// @has - '//h3[@class="code-header in-band"]' 'impl Send for Foowhere T: Send' +// @has - '//h3[@class="code-header in-band"]' 'impl Sync for Foowhere T: Sync' // @count - '//*[@id="implementations-list"]//*[@class="impl has-srclink"]' 0 // @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5 pub struct Foo { diff --git a/src/test/rustdoc/synthetic_auto/complex.rs b/src/test/rustdoc/synthetic_auto/complex.rs index f9017b90caee7..39f78983da2b0 100644 --- a/src/test/rustdoc/synthetic_auto/complex.rs +++ b/src/test/rustdoc/synthetic_auto/complex.rs @@ -21,7 +21,7 @@ mod foo { // @has complex/struct.NotOuter.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \ +// "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K>where K: for<'b> Fn((&'b bool, &'a u8)) \ // -> &'b i8, T: MyTrait<'a>, >::MyItem: Copy, 'a: 'static" pub use foo::{Foo, Inner as NotInner, MyTrait as NotMyTrait, Outer as NotOuter}; diff --git a/src/test/rustdoc/synthetic_auto/lifetimes.rs b/src/test/rustdoc/synthetic_auto/lifetimes.rs index ee1393f9729c1..0c94850e78608 100644 --- a/src/test/rustdoc/synthetic_auto/lifetimes.rs +++ b/src/test/rustdoc/synthetic_auto/lifetimes.rs @@ -10,10 +10,10 @@ where // @has lifetimes/struct.Foo.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl<'c, K> Send for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static" +// "impl<'c, K> Send for Foo<'c, K>where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static" // // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl<'c, K> Sync for Foo<'c, K> where K: Sync" +// "impl<'c, K> Sync for Foo<'c, K>where K: Sync" pub struct Foo<'c, K: 'c> { inner_field: Inner<'c, K>, } diff --git a/src/test/rustdoc/synthetic_auto/manual.rs b/src/test/rustdoc/synthetic_auto/manual.rs index 49bad162211b7..35047e3e8c071 100644 --- a/src/test/rustdoc/synthetic_auto/manual.rs +++ b/src/test/rustdoc/synthetic_auto/manual.rs @@ -1,6 +1,6 @@ // @has manual/struct.Foo.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// 'impl Sync for Foo where T: Sync' +// 'impl Sync for Foowhere T: Sync' // // @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // 'impl Send for Foo' diff --git a/src/test/rustdoc/synthetic_auto/nested.rs b/src/test/rustdoc/synthetic_auto/nested.rs index 69edbee619e31..09587bcc30f13 100644 --- a/src/test/rustdoc/synthetic_auto/nested.rs +++ b/src/test/rustdoc/synthetic_auto/nested.rs @@ -10,10 +10,10 @@ where // @has nested/struct.Foo.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// 'impl Send for Foo where T: Copy' +// 'impl Send for Foowhere T: Copy' // // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// 'impl Sync for Foo where T: Sync' +// 'impl Sync for Foowhere T: Sync' pub struct Foo { inner_field: Inner, } diff --git a/src/test/rustdoc/synthetic_auto/no-redundancy.rs b/src/test/rustdoc/synthetic_auto/no-redundancy.rs index 16ab876e829ef..41375decc8a4a 100644 --- a/src/test/rustdoc/synthetic_auto/no-redundancy.rs +++ b/src/test/rustdoc/synthetic_auto/no-redundancy.rs @@ -10,7 +10,7 @@ where // @has no_redundancy/struct.Outer.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl Send for Outer where T: Send + Copy" +// "impl Send for Outerwhere T: Send + Copy" pub struct Outer { inner_field: Inner, } diff --git a/src/test/rustdoc/synthetic_auto/project.rs b/src/test/rustdoc/synthetic_auto/project.rs index 8b020582563f3..e80b1b1dc9bcf 100644 --- a/src/test/rustdoc/synthetic_auto/project.rs +++ b/src/test/rustdoc/synthetic_auto/project.rs @@ -24,10 +24,10 @@ where // @has project/struct.Foo.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl<'c, K> Send for Foo<'c, K> where K: MyTrait, 'c: 'static" +// "impl<'c, K> Send for Foo<'c, K>where K: MyTrait, 'c: 'static" // // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl<'c, K> Sync for Foo<'c, K> where K: MyTrait, ::MyItem: OtherTrait, \ +// "impl<'c, K> Sync for Foo<'c, K>where K: MyTrait, ::MyItem: OtherTrait, \ // 'c: 'static," pub struct Foo<'c, K: 'c> { inner_field: Inner<'c, K>, diff --git a/src/test/rustdoc/synthetic_auto/self-referential.rs b/src/test/rustdoc/synthetic_auto/self-referential.rs index ccef901b18da3..d15a8de7d2fe1 100644 --- a/src/test/rustdoc/synthetic_auto/self-referential.rs +++ b/src/test/rustdoc/synthetic_auto/self-referential.rs @@ -24,6 +24,6 @@ impl Pattern for Wrapper { // @has self_referential/struct.WriteAndThen.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl Send for WriteAndThen where ::Value: Send" +// "impl Send for WriteAndThenwhere ::Value: Send" pub struct WriteAndThen(pub P1::Value,pub > as Pattern>::Value) where P1: Pattern; diff --git a/src/test/rustdoc/synthetic_auto/static-region.rs b/src/test/rustdoc/synthetic_auto/static-region.rs index 36e985144b0e0..08e9567313e22 100644 --- a/src/test/rustdoc/synthetic_auto/static-region.rs +++ b/src/test/rustdoc/synthetic_auto/static-region.rs @@ -4,7 +4,7 @@ pub trait OwnedTrait<'a> { // @has static_region/struct.Owned.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl Send for Owned where >::Reader: Send" +// "impl Send for Ownedwhere >::Reader: Send" pub struct Owned where T: OwnedTrait<'static> { marker: >::Reader, } diff --git a/src/test/rustdoc/where-clause-order.rs b/src/test/rustdoc/where-clause-order.rs index 3150a8ea05f41..b8502e10a48c4 100644 --- a/src/test/rustdoc/where-clause-order.rs +++ b/src/test/rustdoc/where-clause-order.rs @@ -7,7 +7,7 @@ where } // @has 'foo/trait.SomeTrait.html' -// @has - "//*[@id='impl-SomeTrait%3C(A%2C%20B%2C%20C%2C%20D%2C%20E)%3E-for-(A%2C%20B%2C%20C%2C%20D%2C%20E)']/h3" "impl SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E) where A: PartialOrd + PartialEq, B: PartialOrd + PartialEq, C: PartialOrd + PartialEq, D: PartialOrd + PartialEq, E: PartialOrd + PartialEq + ?Sized, " +// @has - "//*[@id='impl-SomeTrait%3C(A%2C%20B%2C%20C%2C%20D%2C%20E)%3E-for-(A%2C%20B%2C%20C%2C%20D%2C%20E)']/h3" "impl SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)where A: PartialOrd + PartialEq, B: PartialOrd + PartialEq, C: PartialOrd + PartialEq, D: PartialOrd + PartialEq, E: PartialOrd + PartialEq + ?Sized, " impl SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E) where A: PartialOrd + PartialEq, diff --git a/src/test/rustdoc/where.rs b/src/test/rustdoc/where.rs index 50a5722fbaff6..c1a630e25ba0e 100644 --- a/src/test/rustdoc/where.rs +++ b/src/test/rustdoc/where.rs @@ -3,17 +3,17 @@ pub trait MyTrait { fn dummy(&self) { } } -// @has foo/struct.Alpha.html '//pre' "pub struct Alpha(_) where A: MyTrait" +// @has foo/struct.Alpha.html '//pre' "pub struct Alpha(_)where A: MyTrait" pub struct Alpha(A) where A: MyTrait; -// @has foo/trait.Bravo.html '//pre' "pub trait Bravo where B: MyTrait" +// @has foo/trait.Bravo.html '//pre' "pub trait Bravowhere B: MyTrait" pub trait Bravo where B: MyTrait { fn get(&self, B: B); } -// @has foo/fn.charlie.html '//pre' "pub fn charlie() where C: MyTrait" +// @has foo/fn.charlie.html '//pre' "pub fn charlie()where C: MyTrait" pub fn charlie() where C: MyTrait {} pub struct Delta(D); // @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl Delta where D: MyTrait" +// "impl Deltawhere D: MyTrait" impl Delta where D: MyTrait { pub fn delta() {} } @@ -33,19 +33,19 @@ pub trait TraitWhere { } // @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl MyTrait for Echo where E: MyTrait" +// "impl MyTrait for Echowhere E: MyTrait" // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \ -// "impl MyTrait for Echo where E: MyTrait" -impl MyTrait for Echo where E: MyTrait {} +// "impl MyTrait for Echowhere E: MyTrait" +impl MyTrait for Echowhere E: MyTrait {} pub enum Foxtrot { Foxtrot1(F) } // @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl MyTrait for Foxtrot where F: MyTrait" +// "impl MyTrait for Foxtrotwhere F: MyTrait" // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \ -// "impl MyTrait for Foxtrot where F: MyTrait" -impl MyTrait for Foxtrot where F: MyTrait {} +// "impl MyTrait for Foxtrotwhere F: MyTrait" +impl MyTrait for Foxtrotwhere F: MyTrait {} // @has foo/type.Golf.html '//pre[@class="rust typedef"]' \ -// "type Golf where T: Clone, = (T, T)" +// "type Golfwhere T: Clone, = (T, T)" pub type Golf where T: Clone = (T, T); From b112bfeda9dba77c6d7e8eef92125e7002c43e68 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 31 Aug 2022 18:13:59 +0200 Subject: [PATCH 12/23] Add rustdoc GUI test --- src/test/rustdoc-gui/where-whitespace.goml | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/test/rustdoc-gui/where-whitespace.goml diff --git a/src/test/rustdoc-gui/where-whitespace.goml b/src/test/rustdoc-gui/where-whitespace.goml new file mode 100644 index 0000000000000..1a3ff1f491cbb --- /dev/null +++ b/src/test/rustdoc-gui/where-whitespace.goml @@ -0,0 +1,27 @@ +// This test ensures that the where conditions are correctly displayed. +goto: file://|DOC_PATH|/lib2/trait.Whitespace.html +show-text: true +// First, we check in the trait definition if the where clause is "on its own" (not on the same +// line than "pub trait Whitespace"). +compare-elements-position-false: (".item-decl code", ".where.fmt-newline", ("y")) +// And that the code following it isn't on the same line either. +compare-elements-position-false: (".item-decl .fnname", ".where.fmt-newline", ("y")) + +goto: file://|DOC_PATH|/lib2/struct.WhereWhitespace.html +// We make the screen a bit wider to ensure that the trait impl is on one line. +size: (915, 915) + +compare-elements-position-false: ("#method\.new .fnname", "#method\.new .where.fmt-newline", ("y")) +// We ensure that both the trait name and the struct name are on the same line in +// "impl Whitespace<&K> for WhereWhitespace". +compare-elements-position: ( + "#trait-implementations-list .impl h3 .trait", + "#trait-implementations-list .impl h3 .struct", + ("y"), +) +// And we now check that the where condition isn't on the same line. +compare-elements-position-false: ( + "#trait-implementations-list .impl h3 .trait", + "#trait-implementations-list .impl h3 .where.fmt-newline", + ("y"), +) From 54645e880ff88b8c2d242423733e3e0d26e0c1ea Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Tue, 23 Aug 2022 13:25:03 -0600 Subject: [PATCH 13/23] set up rustc_metadata for SessionDiagnostics, port dependency_format.rs --- .../locales/en-US/metadata.ftl | 21 +++++ compiler/rustc_error_messages/src/lib.rs | 1 + .../rustc_metadata/src/dependency_format.rs | 79 ++++++------------- compiler/rustc_metadata/src/errors.rs | 52 ++++++++++++ compiler/rustc_metadata/src/lib.rs | 3 + 5 files changed, 103 insertions(+), 53 deletions(-) create mode 100644 compiler/rustc_error_messages/locales/en-US/metadata.ftl create mode 100644 compiler/rustc_metadata/src/errors.rs diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl new file mode 100644 index 0000000000000..a27e765446427 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -0,0 +1,21 @@ +metadata_rlib_required = + crate `{$crate_name}` required to be available in rlib format, but was not found in this form + +metadata_lib_required = + crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form + +metadata_crate_dep_multiple = + cannot satisfy dependencies so `{$crate_name}` only shows up once + .help = having upstream crates all available in one format will likely make this go away + +metadata_two_panic_runtimes = + cannot link together two panic runtimes: {$prev_name} and {$cur_name} + +metadata_bad_panic_strategy = + the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}` + +metadata_required_panic_strategy = + the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}` + +metadata_incompatible_panic_in_drop_strategy = + the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}` diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 42fb2d538b04d..72174d1f75d12 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -46,6 +46,7 @@ fluent_messages! { infer => "../locales/en-US/infer.ftl", lint => "../locales/en-US/lint.ftl", monomorphize => "../locales/en-US/monomorphize.ftl", + metadata => "../locales/en-US/metadata.ftl", parser => "../locales/en-US/parser.ftl", passes => "../locales/en-US/passes.ftl", plugin_impl => "../locales/en-US/plugin_impl.ftl", diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index b765c34f8e364..5d1082acc0beb 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -52,6 +52,10 @@ //! than finding a number of solutions (there are normally quite a few). use crate::creader::CStore; +use crate::errors::{ + BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired, + RequiredPanicStrategy, RlibRequired, TwoPanicRuntimes, +}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::CrateNum; @@ -136,11 +140,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { if src.rlib.is_some() { continue; } - sess.err(&format!( - "crate `{}` required to be available in rlib format, \ - but was not found in this form", - tcx.crate_name(cnum) - )); + sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum).to_string() }); } return Vec::new(); } @@ -224,12 +224,10 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { Linkage::Static => "rlib", _ => "dylib", }; - sess.err(&format!( - "crate `{}` required to be available in {} format, \ - but was not found in this form", - tcx.crate_name(cnum), - kind - )); + sess.emit_err(LibRequired { + crate_name: tcx.crate_name(cnum).to_string(), + kind: kind.to_string(), + }); } } } @@ -254,16 +252,7 @@ fn add_library( // can be refined over time. if link2 != link || link == RequireStatic { tcx.sess - .struct_err(&format!( - "cannot satisfy dependencies so `{}` only \ - shows up once", - tcx.crate_name(cnum) - )) - .help( - "having upstream crates all available in one format \ - will likely make this go away", - ) - .emit(); + .emit_err(CrateDepMultiple { crate_name: tcx.crate_name(cnum).to_string() }); } } None => { @@ -358,13 +347,9 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { if tcx.is_panic_runtime(cnum) { if let Some((prev, _)) = panic_runtime { - let prev_name = tcx.crate_name(prev); - let cur_name = tcx.crate_name(cnum); - sess.err(&format!( - "cannot link together two \ - panic runtimes: {} and {}", - prev_name, cur_name - )); + let prev_name = tcx.crate_name(prev).to_string(); + let cur_name = tcx.crate_name(cnum).to_string(); + sess.emit_err(TwoPanicRuntimes { prev_name, cur_name }); } panic_runtime = Some(( cnum, @@ -384,13 +369,10 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { // First up, validate that our selected panic runtime is indeed exactly // our same strategy. if found_strategy != desired_strategy { - sess.err(&format!( - "the linked panic runtime `{}` is \ - not compiled with this crate's \ - panic strategy `{}`", - tcx.crate_name(runtime_cnum), - desired_strategy.desc() - )); + sess.emit_err(BadPanicStrategy { + runtime: tcx.crate_name(runtime_cnum).to_string(), + strategy: desired_strategy.desc().to_string(), + }); } // Next up, verify that all other crates are compatible with this panic @@ -407,28 +389,19 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { } if let Some(found_strategy) = tcx.required_panic_strategy(cnum) && desired_strategy != found_strategy { - sess.err(&format!( - "the crate `{}` requires \ - panic strategy `{}` which is \ - incompatible with this crate's \ - strategy of `{}`", - tcx.crate_name(cnum), - found_strategy.desc(), - desired_strategy.desc() - )); + sess.emit_err(RequiredPanicStrategy { + crate_name: tcx.crate_name(cnum).to_string(), + found_strategy: found_strategy.desc().to_string(), + desired_strategy: desired_strategy.desc().to_string() }); } let found_drop_strategy = tcx.panic_in_drop_strategy(cnum); if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy { - sess.err(&format!( - "the crate `{}` is compiled with the \ - panic-in-drop strategy `{}` which is \ - incompatible with this crate's \ - strategy of `{}`", - tcx.crate_name(cnum), - found_drop_strategy.desc(), - tcx.sess.opts.unstable_opts.panic_in_drop.desc() - )); + sess.emit_err(IncompatiblePanicInDropStrategy { + crate_name: tcx.crate_name(cnum).to_string(), + found_strategy: found_drop_strategy.desc().to_string(), + desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop.desc().to_string(), + }); } } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs new file mode 100644 index 0000000000000..702863c376b93 --- /dev/null +++ b/compiler/rustc_metadata/src/errors.rs @@ -0,0 +1,52 @@ +// use rustc_errors::ErrorGuaranteed; +use rustc_macros::SessionDiagnostic; + +#[derive(SessionDiagnostic)] +#[diag(metadata::rlib_required)] +pub struct RlibRequired { + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::lib_required)] +pub struct LibRequired { + pub crate_name: String, + pub kind: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::crate_dep_multiple)] +#[help] +pub struct CrateDepMultiple { + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::two_panic_runtimes)] +pub struct TwoPanicRuntimes { + pub prev_name: String, + pub cur_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::bad_panic_strategy)] +pub struct BadPanicStrategy { + pub runtime: String, + pub strategy: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::required_panic_strategy)] +pub struct RequiredPanicStrategy { + pub crate_name: String, + pub found_strategy: String, + pub desired_strategy: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::incompatible_panic_in_drop_strategy)] +pub struct IncompatiblePanicInDropStrategy { + pub crate_name: String, + pub found_strategy: String, + pub desired_strategy: String, +} diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 6440f3e390cf1..fae5b664f4e43 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -16,6 +16,8 @@ #![feature(never_type)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] extern crate proc_macro; @@ -34,6 +36,7 @@ mod native_libs; mod rmeta; pub mod creader; +pub mod errors; pub mod fs; pub mod locator; From 3ed93107ff0f92a64391e3c0936fb17195d525aa Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Tue, 23 Aug 2022 16:33:28 -0600 Subject: [PATCH 14/23] port native_libs.rs to SessionDiagnostics --- .../locales/en-US/metadata.ftl | 102 ++++++++ compiler/rustc_metadata/src/errors.rs | 232 ++++++++++++++++++ compiler/rustc_metadata/src/native_libs.rs | 182 ++++---------- 3 files changed, 388 insertions(+), 128 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index a27e765446427..0685981f9bb49 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -19,3 +19,105 @@ metadata_required_panic_strategy = metadata_incompatible_panic_in_drop_strategy = the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}` + +metadata_multiple_names_in_link = + multiple `name` arguments in a single `#[link]` attribute + +metadata_multiple_kinds_in_link = + multiple `kind` arguments in a single `#[link]` attribute + +metadata_link_name_form = + link name must be of the form `name = "string"` + +metadata_link_kind_form = + link kind must be of the form `kind = "string"` + +metadata_link_modifiers_form = + link modifiers must be of the form `modifiers = "string"` + +metadata_link_cfg_form = + link cfg must be of the form `cfg(/* predicate */)` + +metadata_wasm_import_form = + wasm import module must be of the form `wasm_import_module = "string"` + +metadata_empty_link_name = + link name must not be empty + .label = empty link name + +metadata_link_framework_apple = + link kind `framework` is only supported on Apple targets + +metadata_framework_only_windows = + link kind `raw-dylib` is only supported on Windows targets + +metadata_unknown_link_kind = + unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib + .label = unknown link kind + +metadata_multiple_link_modifiers = + multiple `modifiers` arguments in a single `#[link]` attribute + +metadata_multiple_cfgs = + multiple `cfg` arguments in a single `#[link]` attribute + +metadata_link_cfg_single_predicate = + link cfg must have a single predicate argument + +metadata_multiple_wasm_import = + multiple `wasm_import_module` arguments in a single `#[link]` attribute + +metadata_unexpected_link_arg = + unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type + +metadata_invalid_link_modifier = + invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed + +metadata_multiple_modifiers = + multiple `{$modifier}` modifiers in a single `modifiers` argument + +metadata_bundle_needs_static = + linking modifier `bundle` is only compatible with `static` linking kind + +metadata_whole_archive_needs_static = + linking modifier `whole-archive` is only compatible with `static` linking kind + +metadata_as_needed_compatibility = + linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds + +metadata_unknown_link_modifier = + unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed + +metadata_incompatible_wasm_link = + `wasm_import_module` is incompatible with other arguments in `#[link]` attributes + +metadata_link_requires_name = + `#[link]` attribute requires a `name = "string"` argument + .label = missing `name` argument + +metadata_raw_dylib_no_nul = + link name must not contain NUL characters if link kind is `raw-dylib` + +metadata_link_ordinal_raw_dylib = + `#[link_ordinal]` is only supported if link kind is `raw-dylib` + +metadata_lib_framework_apple = + library kind `framework` is only supported on Apple targets + +metadata_empty_renaming_target = + an empty renaming target was specified for library `{$lib_name}` + +metadata_renaming_no_link = + renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library + +metadata_multiple_renamings = + multiple renamings were specified for library `{$lib_name}` + +metadata_no_link_mod_override = + overriding linking modifiers from command line is not supported + +metadata_unsupported_abi_i686 = + ABI not supported by `#[link(kind = "raw-dylib")]` on i686 + +metadata_unsupported_abi = + ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 702863c376b93..7e3c9b66fbdf5 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -1,5 +1,6 @@ // use rustc_errors::ErrorGuaranteed; use rustc_macros::SessionDiagnostic; +use rustc_span::Span; #[derive(SessionDiagnostic)] #[diag(metadata::rlib_required)] @@ -50,3 +51,234 @@ pub struct IncompatiblePanicInDropStrategy { pub found_strategy: String, pub desired_strategy: String, } + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_names_in_link)] +pub struct MultipleNamesInLink { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_kinds_in_link)] +pub struct MultipleKindsInLink { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_name_form)] +pub struct LinkNameForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_kind_form)] +pub struct LinkKindForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_modifiers_form)] +pub struct LinkModifiersForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_cfg_form)] +pub struct LinkCfgForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::wasm_import_form)] +pub struct WasmImportForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::empty_link_name, code = "E0454")] +pub struct EmptyLinkName { + #[label] + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_framework_apple, code = "E0455")] +pub struct LinkFrameworkApple { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::framework_only_windows, code = "E0455")] +pub struct FrameworkOnlyWindows { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unknown_link_kind, code = "E0458")] +pub struct UnknownLinkKind { + #[label] + #[primary_span] + pub span: Span, + pub kind: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_link_modifiers)] +pub struct MultipleLinkModifiers { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_cfgs)] +pub struct MultipleCfgs { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_cfg_single_predicate)] +pub struct LinkCfgSinglePredicate { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_wasm_import)] +pub struct MultipleWasmImport { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unexpected_link_arg)] +pub struct UnexpectedLinkArg { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::invalid_link_modifier)] +pub struct InvalidLinkModifier { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_modifiers)] +pub struct MultipleModifiers { + #[primary_span] + pub span: Span, + pub modifier: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::bundle_needs_static)] +pub struct BundleNeedsStatic { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::whole_archive_needs_static)] +pub struct WholeArchiveNeedsStatic { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::as_needed_compatibility)] +pub struct AsNeededCompatibility { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unknown_link_modifier)] +pub struct UnknownLinkModifier { + #[primary_span] + pub span: Span, + pub modifier: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::incompatible_wasm_link)] +pub struct IncompatibleWasmLink { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_requires_name, code = "E0459")] +pub struct LinkRequiresName { + #[label] + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::raw_dylib_no_nul)] +pub struct RawDylibNoNul { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_ordinal_raw_dylib)] +pub struct LinkOrdinalRawDylib { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::lib_framework_apple)] +pub struct LibFrameworkApple; + +#[derive(SessionDiagnostic)] +#[diag(metadata::empty_renaming_target)] +pub struct EmptyRenamingTarget { + pub lib_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::renaming_no_link)] +pub struct RenamingNoLink { + pub lib_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_renamings)] +pub struct MultipleRenamings { + pub lib_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_link_mod_override)] +pub struct NoLinkModOverride { + #[primary_span] + pub span: Option, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unsupported_abi_i686)] +pub struct UnsupportedAbiI686 { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unsupported_abi)] +pub struct UnsupportedAbi { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 8bafe203748f3..e8489232fbda6 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -12,6 +12,17 @@ use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use rustc_target::spec::abi::Abi; +use crate::errors::{ + AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, EmptyRenamingTarget, + FrameworkOnlyWindows, IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, + LinkCfgForm, LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, + LinkNameForm, LinkOrdinalRawDylib, LinkRequiresName, MultipleCfgs, MultipleKindsInLink, + MultipleLinkModifiers, MultipleModifiers, MultipleNamesInLink, MultipleRenamings, + MultipleWasmImport, NoLinkModOverride, RawDylibNoNul, RenamingNoLink, UnexpectedLinkArg, + UnknownLinkKind, UnknownLinkModifier, UnsupportedAbi, UnsupportedAbiI686, WasmImportForm, + WholeArchiveNeedsStatic, +}; + pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { tcx, libs: Vec::new() }; for id in tcx.hir().items() { @@ -66,32 +77,26 @@ impl<'tcx> Collector<'tcx> { match item.name_or_empty() { sym::name => { if name.is_some() { - let msg = "multiple `name` arguments in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleNamesInLink { span: item.span() }); continue; } let Some(link_name) = item.value_str() else { - let msg = "link name must be of the form `name = \"string\"`"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkNameForm { span: item.span() }); continue; }; let span = item.name_value_literal_span().unwrap(); if link_name.is_empty() { - struct_span_err!(sess, span, E0454, "link name must not be empty") - .span_label(span, "empty link name") - .emit(); + sess.emit_err(EmptyLinkName { span }); } name = Some((link_name, span)); } sym::kind => { if kind.is_some() { - let msg = "multiple `kind` arguments in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleKindsInLink { span: item.span() }); continue; } let Some(link_kind) = item.value_str() else { - let msg = "link kind must be of the form `kind = \"string\"`"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkKindForm { span: item.span() }); continue; }; @@ -101,25 +106,13 @@ impl<'tcx> Collector<'tcx> { "dylib" => NativeLibKind::Dylib { as_needed: None }, "framework" => { if !sess.target.is_like_osx { - struct_span_err!( - sess, - span, - E0455, - "link kind `framework` is only supported on Apple targets" - ) - .emit(); + sess.emit_err(LinkFrameworkApple { span }); } NativeLibKind::Framework { as_needed: None } } "raw-dylib" => { if !sess.target.is_like_windows { - struct_span_err!( - sess, - span, - E0455, - "link kind `raw-dylib` is only supported on Windows targets" - ) - .emit(); + sess.emit_err(FrameworkOnlyWindows { span }); } else if !features.raw_dylib { feature_err( &sess.parse_sess, @@ -132,13 +125,7 @@ impl<'tcx> Collector<'tcx> { NativeLibKind::RawDylib } kind => { - let msg = format!( - "unknown link kind `{kind}`, expected one of: \ - static, dylib, framework, raw-dylib" - ); - struct_span_err!(sess, span, E0458, "{}", msg) - .span_label(span, "unknown link kind") - .emit(); + sess.emit_err(UnknownLinkKind { span, kind: kind.to_string() }); continue; } }; @@ -146,32 +133,26 @@ impl<'tcx> Collector<'tcx> { } sym::modifiers => { if modifiers.is_some() { - let msg = - "multiple `modifiers` arguments in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleLinkModifiers { span: item.span() }); continue; } let Some(link_modifiers) = item.value_str() else { - let msg = "link modifiers must be of the form `modifiers = \"string\"`"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkModifiersForm { span: item.span() }); continue; }; modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap())); } sym::cfg => { if cfg.is_some() { - let msg = "multiple `cfg` arguments in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleCfgs { span: item.span() }); continue; } let Some(link_cfg) = item.meta_item_list() else { - let msg = "link cfg must be of the form `cfg(/* predicate */)`"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkCfgForm { span: item.span() }); continue; }; let [NestedMetaItem::MetaItem(link_cfg)] = link_cfg else { - let msg = "link cfg must have a single predicate argument"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkCfgSinglePredicate { span: item.span() }); continue; }; if !features.link_cfg { @@ -187,15 +168,11 @@ impl<'tcx> Collector<'tcx> { } sym::wasm_import_module => { if wasm_import_module.is_some() { - let msg = "multiple `wasm_import_module` arguments \ - in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleWasmImport { span: item.span() }); continue; } let Some(link_wasm_import_module) = item.value_str() else { - let msg = "wasm import module must be of the form \ - `wasm_import_module = \"string\"`"; - sess.span_err(item.span(), msg); + sess.emit_err(WasmImportForm { span: item.span() }); continue; }; wasm_import_module = Some((link_wasm_import_module, item.span())); @@ -243,9 +220,7 @@ impl<'tcx> Collector<'tcx> { import_name_type = Some((link_import_name_type, item.span())); } _ => { - let msg = "unexpected `#[link]` argument, expected one of: \ - name, kind, modifiers, cfg, wasm_import_module, import_name_type"; - sess.span_err(item.span(), msg); + sess.emit_err(UnexpectedLinkArg { span: item.span() }); } } } @@ -257,11 +232,7 @@ impl<'tcx> Collector<'tcx> { let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { Some(m) => (m, modifier.starts_with('+')), None => { - sess.span_err( - span, - "invalid linking modifier syntax, expected '+' or '-' prefix \ - before one of: bundle, verbatim, whole-archive, as-needed", - ); + sess.emit_err(InvalidLinkModifier { span }); continue; } }; @@ -279,10 +250,10 @@ impl<'tcx> Collector<'tcx> { } let assign_modifier = |dst: &mut Option| { if dst.is_some() { - let msg = format!( - "multiple `{modifier}` modifiers in a single `modifiers` argument" - ); - sess.span_err(span, &msg); + sess.emit_err(MultipleModifiers { + span, + modifier: modifier.to_string(), + }); } else { *dst = Some(value); } @@ -292,11 +263,7 @@ impl<'tcx> Collector<'tcx> { assign_modifier(bundle) } ("bundle", _) => { - sess.span_err( - span, - "linking modifier `bundle` is only compatible with \ - `static` linking kind", - ); + sess.emit_err(BundleNeedsStatic { span }); } ("verbatim", _) => { @@ -308,11 +275,7 @@ impl<'tcx> Collector<'tcx> { assign_modifier(whole_archive) } ("whole-archive", _) => { - sess.span_err( - span, - "linking modifier `whole-archive` is only compatible with \ - `static` linking kind", - ); + sess.emit_err(WholeArchiveNeedsStatic { span }); } ("as-needed", Some(NativeLibKind::Dylib { as_needed })) @@ -321,21 +284,14 @@ impl<'tcx> Collector<'tcx> { assign_modifier(as_needed) } ("as-needed", _) => { - sess.span_err( - span, - "linking modifier `as-needed` is only compatible with \ - `dylib` and `framework` linking kinds", - ); + sess.emit_err(AsNeededCompatibility { span }); } _ => { - sess.span_err( + sess.emit_err(UnknownLinkModifier { span, - format!( - "unknown linking modifier `{modifier}`, expected one of: \ - bundle, verbatim, whole-archive, as-needed" - ), - ); + modifier: modifier.to_string(), + }); } } } @@ -343,19 +299,10 @@ impl<'tcx> Collector<'tcx> { if let Some((_, span)) = wasm_import_module { if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() { - let msg = "`wasm_import_module` is incompatible with \ - other arguments in `#[link]` attributes"; - sess.span_err(span, msg); + sess.emit_err(IncompatibleWasmLink { span }); } } else if name.is_none() { - struct_span_err!( - sess, - m.span, - E0459, - "`#[link]` attribute requires a `name = \"string\"` argument" - ) - .span_label(m.span, "missing `name` argument") - .emit(); + sess.emit_err(LinkRequiresName { span: m.span }); } // Do this outside of the loop so that `import_name_type` can be specified before `kind`. @@ -369,10 +316,7 @@ impl<'tcx> Collector<'tcx> { let dll_imports = match kind { Some(NativeLibKind::RawDylib) => { if let Some((name, span)) = name && name.as_str().contains('\0') { - sess.span_err( - span, - "link name must not contain NUL characters if link kind is `raw-dylib`", - ); + sess.emit_err(RawDylibNoNul { span }); } foreign_mod_items .iter() @@ -401,10 +345,7 @@ impl<'tcx> Collector<'tcx> { .iter() .find(|a| a.has_name(sym::link_ordinal)) .unwrap(); - sess.span_err( - link_ordinal_attr.span, - "`#[link_ordinal]` is only supported if link kind is `raw-dylib`", - ); + sess.emit_err(LinkOrdinalRawDylib { span: link_ordinal_attr.span }); } } @@ -430,7 +371,7 @@ impl<'tcx> Collector<'tcx> { for lib in &self.tcx.sess.opts.libs { if let NativeLibKind::Framework { .. } = lib.kind && !self.tcx.sess.target.is_like_osx { // Cannot check this when parsing options because the target is not yet available. - self.tcx.sess.err("library kind `framework` is only supported on Apple targets"); + self.tcx.sess.emit_err(LibFrameworkApple); } if let Some(ref new_name) = lib.new_name { let any_duplicate = self @@ -439,23 +380,11 @@ impl<'tcx> Collector<'tcx> { .filter_map(|lib| lib.name.as_ref()) .any(|n| n.as_str() == lib.name); if new_name.is_empty() { - self.tcx.sess.err(format!( - "an empty renaming target was specified for library `{}`", - lib.name - )); + self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: lib.name.clone() }); } else if !any_duplicate { - self.tcx.sess.err(format!( - "renaming of the library `{}` was specified, \ - however this crate contains no `#[link(...)]` \ - attributes referencing this library", - lib.name - )); + self.tcx.sess.emit_err(RenamingNoLink { lib_name: lib.name.clone() }); } else if !renames.insert(&lib.name) { - self.tcx.sess.err(format!( - "multiple renamings were \ - specified for library `{}`", - lib.name - )); + self.tcx.sess.emit_err(MultipleRenamings { lib_name: lib.name.clone() }); } } } @@ -480,10 +409,13 @@ impl<'tcx> Collector<'tcx> { // involved or not, library reordering and kind overriding without // explicit `:rename` in particular. if lib.has_modifiers() || passed_lib.has_modifiers() { - let msg = "overriding linking modifiers from command line is not supported"; match lib.foreign_module { - Some(def_id) => self.tcx.sess.span_err(self.tcx.def_span(def_id), msg), - None => self.tcx.sess.err(msg), + Some(def_id) => self.tcx.sess.emit_err(NoLinkModOverride { + span: Some(self.tcx.def_span(def_id)), + }), + None => { + self.tcx.sess.emit_err(NoLinkModOverride { span: None }) + } }; } if passed_lib.kind != NativeLibKind::Unspecified { @@ -562,20 +494,14 @@ impl<'tcx> Collector<'tcx> { DllCallingConvention::Vectorcall(self.i686_arg_list_size(item)) } _ => { - self.tcx.sess.span_fatal( - item.span, - r#"ABI not supported by `#[link(kind = "raw-dylib")]` on i686"#, - ); + self.tcx.sess.emit_fatal(UnsupportedAbiI686 { span: item.span }); } } } else { match abi { Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C, _ => { - self.tcx.sess.span_fatal( - item.span, - r#"ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture"#, - ); + self.tcx.sess.emit_fatal(UnsupportedAbi { span: item.span }); } } }; From f7e462a6c7faaea4bfce236fb94b4622ea8260ef Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Tue, 23 Aug 2022 16:40:43 -0600 Subject: [PATCH 15/23] port encoder.rs to SessionDiagnostics --- .../locales/en-US/metadata.ftl | 9 +++++++++ compiler/rustc_metadata/src/errors.rs | 18 ++++++++++++++++++ compiler/rustc_metadata/src/rmeta/encoder.rs | 7 ++++--- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index 0685981f9bb49..8cce1f007e227 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -121,3 +121,12 @@ metadata_unsupported_abi_i686 = metadata_unsupported_abi = ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture + +metadata_fail_create_file_encoder = + failed to create file encoder: {$err} + +metadata_fail_seek_file = + failed to seek the file: {$err} + +metadata_fail_write_file = + failed to write to the file: {$err} diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 7e3c9b66fbdf5..5edc59bf9e923 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -282,3 +282,21 @@ pub struct UnsupportedAbi { #[primary_span] pub span: Span, } + +#[derive(SessionDiagnostic)] +#[diag(metadata::fail_create_file_encoder)] +pub struct FailCreateFileEncoder { + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::fail_seek_file)] +pub struct FailSeekFile { + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::fail_write_file)] +pub struct FailWriteFile { + pub err: String, +} diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 3482d9f04514e..2b1f9f17a3c85 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1,3 +1,4 @@ +use crate::errors::{FailCreateFileEncoder, FailSeekFile, FailWriteFile}; use crate::rmeta::def_path_hash_map::DefPathHashMapRef; use crate::rmeta::table::TableBuilder; use crate::rmeta::*; @@ -2269,7 +2270,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { let mut encoder = opaque::FileEncoder::new(path) - .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to create file encoder: {}", err))); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailCreateFileEncoder { err: err.to_string() })); encoder.emit_raw_bytes(METADATA_HEADER); // Will be filled with the root position after encoding everything. @@ -2314,10 +2315,10 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { // Encode the root position. let header = METADATA_HEADER.len(); file.seek(std::io::SeekFrom::Start(header as u64)) - .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to seek the file: {}", err))); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err: err.to_string() })); let pos = root.position.get(); file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8]) - .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to write to the file: {}", err))); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err: err.to_string() })); // Return to the position where we are before writing the root position. file.seek(std::io::SeekFrom::Start(pos_before_seek)).unwrap(); From 32e1823b2275cf55a598e65c5093a28122b4039f Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Tue, 23 Aug 2022 17:03:49 -0600 Subject: [PATCH 16/23] port creader.rs to SessionDiagnostics --- .../locales/en-US/metadata.ftl | 28 ++++++++++ compiler/rustc_metadata/src/creader.rs | 56 ++++++++----------- compiler/rustc_metadata/src/errors.rs | 52 +++++++++++++++++ 3 files changed, 102 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index 8cce1f007e227..3ce1275a89919 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -130,3 +130,31 @@ metadata_fail_seek_file = metadata_fail_write_file = failed to write to the file: {$err} + +metadata_crate_not_panic_runtime = + the crate `{$crate_name}` is not a panic runtime + +metadata_no_panic_strategy = + the crate `{$crate_name}` does not have the panic strategy `{$strategy}` + +metadata_profiler_builtins_needs_core = + `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]` + +metadata_not_profiler_runtime = + the crate `{$crate_name}` is not a profiler runtime + +metadata_no_multiple_global_alloc = + cannot define multiple global allocators + .label = cannot define a new global allocator + +metadata_prev_global_alloc = + previous global allocator defined here + +metadata_conflicting_global_alloc = + the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name} + +metadata_global_alloc_required = + no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait + +metadata_no_transitive_needs_dep = + the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}` diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 708d0b1fd8a30..f9aa3733f6a37 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1,5 +1,9 @@ //! Validates all used crates and extern libraries and loads their metadata +use crate::errors::{ + ConflictingGlobalAlloc, CrateNotPanicRuntime, GlobalAllocRequired, NoMultipleGlobalAlloc, + NoPanicStrategy, NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore, +}; use crate::locator::{CrateError, CrateLocator, CratePaths}; use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}; @@ -746,15 +750,13 @@ impl<'a> CrateLoader<'a> { // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. if !data.is_panic_runtime() { - self.sess.err(&format!("the crate `{}` is not a panic runtime", name)); + self.sess.emit_err(CrateNotPanicRuntime { crate_name: name.to_string() }); } if data.required_panic_strategy() != Some(desired_strategy) { - self.sess.err(&format!( - "the crate `{}` does not have the panic \ - strategy `{}`", - name, - desired_strategy.desc() - )); + self.sess.emit_err(NoPanicStrategy { + crate_name: name.to_string(), + strategy: desired_strategy.desc().to_string(), + }); } self.cstore.injected_panic_runtime = Some(cnum); @@ -774,10 +776,7 @@ impl<'a> CrateLoader<'a> { let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime); if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) { - self.sess.err( - "`profiler_builtins` crate (required by compiler options) \ - is not compatible with crate attribute `#![no_core]`", - ); + self.sess.emit_err(ProfilerBuiltinsNeedsCore); } let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; }; @@ -785,18 +784,14 @@ impl<'a> CrateLoader<'a> { // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.is_profiler_runtime() { - self.sess.err(&format!("the crate `{}` is not a profiler runtime", name)); + self.sess.emit_err(NotProfilerRuntime { crate_name: name.to_string() }); } } fn inject_allocator_crate(&mut self, krate: &ast::Crate) { self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) { [span1, span2, ..] => { - self.sess - .struct_span_err(*span2, "cannot define multiple global allocators") - .span_label(*span2, "cannot define a new global allocator") - .span_label(*span1, "previous global allocator defined here") - .emit(); + self.sess.emit_err(NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); true } spans => !spans.is_empty(), @@ -832,11 +827,10 @@ impl<'a> CrateLoader<'a> { if data.has_global_allocator() { match global_allocator { Some(other_crate) => { - self.sess.err(&format!( - "the `#[global_allocator]` in {} conflicts with global allocator in: {}", - other_crate, - data.name() - )); + self.sess.emit_err(ConflictingGlobalAlloc { + crate_name: data.name().to_string(), + other_crate_name: other_crate.to_string(), + }); } None => global_allocator = Some(data.name()), } @@ -855,10 +849,7 @@ impl<'a> CrateLoader<'a> { if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator) && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) { - self.sess.err( - "no global memory allocator found but one is required; link to std or add \ - `#[global_allocator]` to a static item that implements the GlobalAlloc trait", - ); + self.sess.emit_err(GlobalAllocRequired); } self.cstore.allocator_kind = Some(AllocatorKind::Default); } @@ -882,14 +873,11 @@ impl<'a> CrateLoader<'a> { for dep in self.cstore.crate_dependencies_in_reverse_postorder(krate) { let data = self.cstore.get_crate_data(dep); if needs_dep(&data) { - self.sess.err(&format!( - "the crate `{}` cannot depend \ - on a crate that needs {}, but \ - it depends on `{}`", - self.cstore.get_crate_data(krate).name(), - what, - data.name() - )); + self.sess.emit_err(NoTransitiveNeedsDep { + crate_name: self.cstore.get_crate_data(krate).name().to_string(), + needs_crate_name: what.to_string(), + deps_crate_name: data.name().to_string(), + }); } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 5edc59bf9e923..3d025e89857c9 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -300,3 +300,55 @@ pub struct FailSeekFile { pub struct FailWriteFile { pub err: String, } + +#[derive(SessionDiagnostic)] +#[diag(metadata::crate_not_panic_runtime)] +pub struct CrateNotPanicRuntime { + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_panic_strategy)] +pub struct NoPanicStrategy { + pub crate_name: String, + pub strategy: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::profiler_builtins_needs_core)] +pub struct ProfilerBuiltinsNeedsCore; + +#[derive(SessionDiagnostic)] +#[diag(metadata::not_profiler_runtime)] +pub struct NotProfilerRuntime { + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_multiple_global_alloc)] +pub struct NoMultipleGlobalAlloc { + #[primary_span] + #[label] + pub span2: Span, + #[label(metadata::prev_global_alloc)] + pub span1: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::conflicting_global_alloc)] +pub struct ConflictingGlobalAlloc { + pub crate_name: String, + pub other_crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::global_alloc_required)] +pub struct GlobalAllocRequired; + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_transitive_needs_dep)] +pub struct NoTransitiveNeedsDep { + pub crate_name: String, + pub needs_crate_name: String, + pub deps_crate_name: String, +} From bd8e312d73f07517e24a58a201e8524ebe4da8da Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Tue, 23 Aug 2022 17:16:04 -0600 Subject: [PATCH 17/23] port fs.rs to SessionDiagnostics --- .../locales/en-US/metadata.ftl | 12 +++++++++ compiler/rustc_metadata/src/errors.rs | 26 +++++++++++++++++++ compiler/rustc_metadata/src/fs.rs | 26 ++++++++++++------- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index 3ce1275a89919..a4881dbc76455 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -158,3 +158,15 @@ metadata_global_alloc_required = metadata_no_transitive_needs_dep = the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}` + +metadata_failed_write_error = + failed to write {$filename}: {$err} + +metadata_failed_create_tempdir = + couldn't create a temp dir: {$err} + +metadata_failed_create_file = + failed to create the file {$filename}: {$err} + +metadata_failed_create_encoded_metadata = + failed to create encoded metadata from file: {$err} diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 3d025e89857c9..c373e49ba4958 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -352,3 +352,29 @@ pub struct NoTransitiveNeedsDep { pub needs_crate_name: String, pub deps_crate_name: String, } + +#[derive(SessionDiagnostic)] +#[diag(metadata::failed_write_error)] +pub struct FailedWriteError { + pub filename: String, + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::failed_create_tempdir)] +pub struct FailedCreateTempdir { + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::failed_create_file)] +pub struct FailedCreateFile { + pub filename: String, + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::failed_create_encoded_metadata)] +pub struct FailedCreateEncodedMetadata { + pub err: String, +} diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index e6072901aaa43..67c18766c5959 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -1,3 +1,6 @@ +use crate::errors::{ + FailedCreateEncodedMetadata, FailedCreateFile, FailedCreateTempdir, FailedWriteError, +}; use crate::{encode_metadata, EncodedMetadata}; use rustc_data_structures::temp_dir::MaybeTempDir; @@ -24,7 +27,10 @@ pub fn emit_metadata(sess: &Session, metadata: &[u8], tmpdir: &MaybeTempDir) -> let result = fs::write(&out_filename, metadata); if let Err(e) = result { - sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); + sess.emit_fatal(FailedWriteError { + filename: out_filename.display().to_string(), + err: e.to_string(), + }); } out_filename @@ -65,7 +71,7 @@ pub fn encode_and_write_metadata( let metadata_tmpdir = TempFileBuilder::new() .prefix("rmeta") .tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new(""))) - .unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err))); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailedCreateTempdir { err: err.to_string() })); let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps); let metadata_filename = metadata_tmpdir.as_ref().join(METADATA_FILENAME); @@ -74,11 +80,10 @@ pub fn encode_and_write_metadata( match metadata_kind { MetadataKind::None => { std::fs::File::create(&metadata_filename).unwrap_or_else(|e| { - tcx.sess.fatal(&format!( - "failed to create the file {}: {}", - metadata_filename.display(), - e - )) + tcx.sess.emit_fatal(FailedCreateFile { + filename: metadata_filename.display().to_string(), + err: e.to_string(), + }); }); } MetadataKind::Uncompressed | MetadataKind::Compressed => { @@ -94,7 +99,10 @@ pub fn encode_and_write_metadata( let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata); let (metadata_filename, metadata_tmpdir) = if need_metadata_file { if let Err(e) = non_durable_rename(&metadata_filename, &out_filename) { - tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); + tcx.sess.emit_fatal(FailedWriteError { + filename: out_filename.display().to_string(), + err: e.to_string(), + }); } if tcx.sess.opts.json_artifact_notifications { tcx.sess @@ -110,7 +118,7 @@ pub fn encode_and_write_metadata( // Load metadata back to memory: codegen may need to include it in object files. let metadata = EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|e| { - tcx.sess.fatal(&format!("failed to create encoded metadata from file: {}", e)) + tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err: e.to_string() }); }); let need_metadata_module = metadata_kind == MetadataKind::Compressed; From d0ba1fbaa4f73b6edf27346817b1f74fb352945e Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Wed, 24 Aug 2022 12:14:41 -0600 Subject: [PATCH 18/23] port of locator.rs to SessionDiagnostics, fix some of the errors revealed by tests, manually add a panic to test for dead code --- .../locales/en-US/metadata.ftl | 55 +++ compiler/rustc_metadata/src/errors.rs | 257 ++++++++++++- compiler/rustc_metadata/src/locator.rs | 348 +++++++----------- compiler/rustc_metadata/src/native_libs.rs | 1 - 4 files changed, 448 insertions(+), 213 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index a4881dbc76455..e3e58cf8bed7e 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -170,3 +170,58 @@ metadata_failed_create_file = metadata_failed_create_encoded_metadata = failed to create encoded metadata from file: {$err} + +metadata_non_ascii_name = + cannot load a crate with a non-ascii name `{$crate_name}` + +metadata_extern_location_not_exist = + extern location for {$crate_name} does not exist: {$location} + +metadata_extern_location_not_file = + extern location for {$crate_name} is not a file: {$location} + +metadata_multiple_candidates = + multiple {$flavor} candidates for `{$crate_name}` found + +metadata_multiple_matching_crates = + multiple matching crates for `{$crate_name}` + .note = candidates:{$candidates} + +metadata_symbol_conflicts_current = + the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two. + +metadata_symbol_conflicts_others = + found two different crates with name `{$crate_name}` that are not distinguished by differing `-C metadata`. This will result in symbol conflicts between the two. + +metadata_stable_crate_id_collision = + found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values. + +metadata_dl_error = + {$err} + +metadata_newer_crate_version = + found possibly newer version of crate `{$crate_name}`{$add_info} + .note = perhaps that crate needs to be recompiled? + +metadata_found_crate_versions = + the following crate versions were found:{$found_crates} + +metadata_no_crate_with_triple = + couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info} + +metadata_found_staticlib = + found staticlib `{$crate_name}` instead of rlib or dylib{$add_info} + .help = please recompile that crate using --crate-type lib + +metadata_incompatible_rustc = + found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info} + .help = please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first) + +metadata_invalid_meta_files = + found invalid metadata files for crate `{$crate_name}`{$add_info} + +metadata_cannot_find_crate = + can't find crate for `{$crate_name}`{$add_info} + +metadata_no_dylib_plugin = + plugin `{$crate_name}` only found in rlib format, but must be available in dylib format diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index c373e49ba4958..d3f35ca8d164f 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -1,6 +1,10 @@ -// use rustc_errors::ErrorGuaranteed; +use std::path::PathBuf; + +use rustc_errors::{DiagnosticId, ErrorGuaranteed}; use rustc_macros::SessionDiagnostic; -use rustc_span::Span; +use rustc_session::{config, SessionDiagnostic}; +use rustc_span::{sym, Span, Symbol}; +use rustc_target::spec::TargetTriple; #[derive(SessionDiagnostic)] #[diag(metadata::rlib_required)] @@ -104,8 +108,8 @@ pub struct WasmImportForm { #[derive(SessionDiagnostic)] #[diag(metadata::empty_link_name, code = "E0454")] pub struct EmptyLinkName { - #[label] #[primary_span] + #[label] pub span: Span, } @@ -126,8 +130,8 @@ pub struct FrameworkOnlyWindows { #[derive(SessionDiagnostic)] #[diag(metadata::unknown_link_kind, code = "E0458")] pub struct UnknownLinkKind { - #[label] #[primary_span] + #[label] pub span: Span, pub kind: String, } @@ -221,8 +225,8 @@ pub struct IncompatibleWasmLink { #[derive(SessionDiagnostic)] #[diag(metadata::link_requires_name, code = "E0459")] pub struct LinkRequiresName { - #[label] #[primary_span] + #[label] pub span: Span, } @@ -378,3 +382,246 @@ pub struct FailedCreateFile { pub struct FailedCreateEncodedMetadata { pub err: String, } + +#[derive(SessionDiagnostic)] +#[diag(metadata::non_ascii_name)] +pub struct NonAsciiName { + #[primary_span] + pub span: Span, + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::extern_location_not_exist)] +pub struct ExternLocationNotExist { + #[primary_span] + pub span: Span, + pub crate_name: String, + pub location: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::extern_location_not_file)] +pub struct ExternLocationNotFile { + #[primary_span] + pub span: Span, + pub crate_name: String, + pub location: String, +} + +pub struct MultipleCandidates { + pub span: Span, + pub flavor: String, + pub crate_name: String, + pub candidates: Vec, +} + +impl SessionDiagnostic<'_> for MultipleCandidates { + fn into_diagnostic( + self, + sess: &'_ rustc_session::parse::ParseSess, + ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = sess.struct_err(rustc_errors::fluent::metadata::multiple_candidates); + diag.set_arg("crate_name", self.crate_name); + diag.set_arg("flavor", self.flavor); + diag.code(DiagnosticId::Error("E0465".into())); + diag.set_span(self.span); + for (i, candidate) in self.candidates.iter().enumerate() { + diag.span_note(self.span, &format!("candidate #{}: {}", i + 1, candidate.display())); + } + diag + } +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_matching_crates, code = "E0464")] +#[note] +pub struct MultipleMatchingCrates { + #[primary_span] + pub span: Span, + pub crate_name: String, + pub candidates: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::symbol_conflicts_current, code = "E0519")] +pub struct SymbolConflictsCurrent { + #[primary_span] + pub span: Span, + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::symbol_conflicts_others, code = "E0523")] +pub struct SymbolConflictsOthers { + #[primary_span] + pub span: Span, + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::stable_crate_id_collision)] +pub struct StableCrateIdCollision { + #[primary_span] + pub span: Span, + pub crate_name0: String, + pub crate_name1: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::dl_error)] +pub struct DlError { + #[primary_span] + pub span: Span, + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::newer_crate_version, code = "E0460")] +#[note] +#[note(metadata::found_crate_versions)] +pub struct NewerCrateVersion { + #[primary_span] + pub span: Span, + pub crate_name: String, + pub add_info: String, + pub found_crates: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_crate_with_triple, code = "E0461")] +#[note(metadata::found_crate_versions)] +pub struct NoCrateWithTriple { + #[primary_span] + pub span: Span, + pub crate_name: String, + pub locator_triple: String, + pub add_info: String, + pub found_crates: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::found_staticlib, code = "E0462")] +#[note(metadata::found_crate_versions)] +#[help] +pub struct FoundStaticlib { + #[primary_span] + pub span: Span, + pub crate_name: String, + pub add_info: String, + pub found_crates: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::incompatible_rustc, code = "E0514")] +#[note(metadata::found_crate_versions)] +#[help] +pub struct IncompatibleRustc { + #[primary_span] + pub span: Span, + pub crate_name: String, + pub add_info: String, + pub found_crates: String, + pub rustc_version: String, +} + +pub struct InvalidMetadataFiles { + pub span: Span, + pub crate_name: String, + pub add_info: String, + pub crate_rejections: Vec, +} + +impl SessionDiagnostic<'_> for InvalidMetadataFiles { + fn into_diagnostic( + self, + sess: &'_ rustc_session::parse::ParseSess, + ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = sess.struct_err(rustc_errors::fluent::metadata::invalid_meta_files); + diag.set_arg("crate_name", self.crate_name); + diag.set_arg("add_info", self.add_info); + diag.code(DiagnosticId::Error("E0786".into())); + diag.set_span(self.span); + for crate_rejection in self.crate_rejections { + diag.note(crate_rejection); + } + diag + } +} + +pub struct CannotFindCrate { + pub span: Span, + pub crate_name: String, + pub crate_name_symbol: Symbol, + pub add_info: String, + pub missing_core: bool, + pub current_crate: String, + pub is_nightly_build: bool, + pub profiler_runtime: Symbol, + pub locator_triple: TargetTriple, +} + +impl SessionDiagnostic<'_> for CannotFindCrate { + fn into_diagnostic( + self, + sess: &'_ rustc_session::parse::ParseSess, + ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = sess.struct_err(rustc_errors::fluent::metadata::cannot_find_crate); + diag.set_arg("crate_name", self.crate_name.clone()); + diag.set_arg("add_info", self.add_info); + diag.code(DiagnosticId::Error("E0463".into())); + diag.set_span(self.span); + // FIXME: Find a way to distill this logic down into the derived SessionDiagnostic form + if (self.crate_name_symbol == sym::std || self.crate_name_symbol == sym::core) + && self.locator_triple != TargetTriple::from_triple(config::host_triple()) + { + if self.missing_core { + diag.note(&format!("the `{}` target may not be installed", self.locator_triple)); + } else { + diag.note(&format!( + "the `{}` target may not support the standard library", + self.locator_triple + )); + } + // NOTE: this suggests using rustup, even though the user may not have it installed. + // That's because they could choose to install it; or this may give them a hint which + // target they need to install from their distro. + if self.missing_core { + diag.help(&format!( + "consider downloading the target with `rustup target add {}`", + self.locator_triple + )); + } + // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway. + // NOTE: this is a dummy span if `extern crate std` was injected by the compiler. + // If it's not a dummy, that means someone added `extern crate std` explicitly and + // `#![no_std]` won't help. + if !self.missing_core && self.span.is_dummy() { + diag.note(&format!( + "`std` is required by `{}` because it does not declare `#![no_std]`", + self.current_crate + )); + } + if self.is_nightly_build { + diag.help("consider building the standard library from source with `cargo build -Zbuild-std`"); + } + } else if self.crate_name_symbol == self.profiler_runtime { + diag.note("the compiler may have been built without the profiler runtime"); + } else if self.crate_name.starts_with("rustc_") { + diag.help( + "maybe you need to install the missing components with: \ + `rustup component add rust-src rustc-dev llvm-tools-preview`", + ); + } + diag.span_label(self.span, "can't find crate"); + diag + } +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_dylib_plugin, code = "E0457")] +pub struct NoDylibPlugin { + #[primary_span] + pub span: Span, + pub crate_name: String, +} diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 2c1c84b0be26a..83c8756078ec4 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -213,6 +213,12 @@ //! metadata::locator or metadata::creader for all the juicy details! use crate::creader::Library; +use crate::errors::{ + CannotFindCrate, DlError, ExternLocationNotExist, ExternLocationNotFile, FoundStaticlib, + IncompatibleRustc, InvalidMetadataFiles, MultipleCandidates, MultipleMatchingCrates, + NewerCrateVersion, NoCrateWithTriple, NoDylibPlugin, NonAsciiName, StableCrateIdCollision, + SymbolConflictsCurrent, SymbolConflictsOthers, +}; use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -220,14 +226,14 @@ use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; -use rustc_errors::{struct_span_err, FatalError}; +use rustc_errors::FatalError; use rustc_session::config::{self, CrateType}; use rustc_session::cstore::{CrateSource, MetadataLoader}; use rustc_session::filesearch::FileSearch; use rustc_session::search_paths::PathKind; use rustc_session::utils::CanonicalizedPath; use rustc_session::Session; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_target::spec::{Target, TargetTriple}; @@ -938,41 +944,33 @@ impl fmt::Display for MetadataError<'_> { impl CrateError { pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) { - let mut diag = match self { - CrateError::NonAsciiName(crate_name) => sess.struct_span_err( - span, - &format!("cannot load a crate with a non-ascii name `{}`", crate_name), - ), - CrateError::ExternLocationNotExist(crate_name, loc) => sess.struct_span_err( - span, - &format!("extern location for {} does not exist: {}", crate_name, loc.display()), - ), - CrateError::ExternLocationNotFile(crate_name, loc) => sess.struct_span_err( - span, - &format!("extern location for {} is not a file: {}", crate_name, loc.display()), - ), + match self { + CrateError::NonAsciiName(crate_name) => { + sess.emit_err(NonAsciiName { span, crate_name: crate_name.to_string() }); + } + CrateError::ExternLocationNotExist(crate_name, loc) => { + sess.emit_err(ExternLocationNotExist { + span, + crate_name: crate_name.to_string(), + location: loc.display().to_string(), + }); + } + CrateError::ExternLocationNotFile(crate_name, loc) => { + sess.emit_err(ExternLocationNotFile { + span, + crate_name: crate_name.to_string(), + location: loc.display().to_string(), + }); + } CrateError::MultipleCandidates(crate_name, flavor, candidates) => { - let mut err = struct_span_err!( - sess, + sess.emit_err(MultipleCandidates { span, - E0465, - "multiple {} candidates for `{}` found", - flavor, - crate_name, - ); - for (i, candidate) in candidates.iter().enumerate() { - err.span_note(span, &format!("candidate #{}: {}", i + 1, candidate.display())); - } - err + flavor: flavor.to_string(), + crate_name: crate_name.to_string(), + candidates, + }); } CrateError::MultipleMatchingCrates(crate_name, libraries) => { - let mut err = struct_span_err!( - sess, - span, - E0464, - "multiple matching crates for `{}`", - crate_name - ); let mut libraries: Vec<_> = libraries.into_values().collect(); // Make ordering of candidates deterministic. // This has to `clone()` to work around lifetime restrictions with `sort_by_key()`. @@ -1000,223 +998,159 @@ impl CrateError { s }) .collect::(); - err.note(&format!("candidates:{}", candidates)); - err + sess.emit_err(MultipleMatchingCrates { + span, + crate_name: crate_name.to_string(), + candidates, + }); + } + CrateError::SymbolConflictsCurrent(root_name) => { + sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name.to_string() }); + } + CrateError::SymbolConflictsOthers(root_name) => { + sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name.to_string() }); } - CrateError::SymbolConflictsCurrent(root_name) => struct_span_err!( - sess, - span, - E0519, - "the current crate is indistinguishable from one of its dependencies: it has the \ - same crate-name `{}` and was compiled with the same `-C metadata` arguments. \ - This will result in symbol conflicts between the two.", - root_name, - ), - CrateError::SymbolConflictsOthers(root_name) => struct_span_err!( - sess, - span, - E0523, - "found two different crates with name `{}` that are not distinguished by differing \ - `-C metadata`. This will result in symbol conflicts between the two.", - root_name, - ), CrateError::StableCrateIdCollision(crate_name0, crate_name1) => { - let msg = format!( - "found crates (`{}` and `{}`) with colliding StableCrateId values.", - crate_name0, crate_name1 - ); - sess.struct_span_err(span, &msg) + sess.emit_err(StableCrateIdCollision { + span, + crate_name0: crate_name0.to_string(), + crate_name1: crate_name1.to_string(), + }); + } + CrateError::DlOpen(s) | CrateError::DlSym(s) => { + sess.emit_err(DlError { span, err: s.to_string() }); } - CrateError::DlOpen(s) | CrateError::DlSym(s) => sess.struct_span_err(span, &s), CrateError::LocatorCombined(locator) => { let crate_name = locator.crate_name; - let add = match &locator.root { + let add_info = match &locator.root { None => String::new(), Some(r) => format!(" which `{}` depends on", r.name), }; - let mut msg = "the following crate versions were found:".to_string(); - let mut err = if !locator.crate_rejections.via_hash.is_empty() { - let mut err = struct_span_err!( - sess, - span, - E0460, - "found possibly newer version of crate `{}`{}", - crate_name, - add, - ); - err.note("perhaps that crate needs to be recompiled?"); + // FIXME: Is there any way to get these notes and helps onto every diagnostic in this + // huge branch arm without changing them all to manual implementations? + let mut global_loc_notes = Vec::new(); + let mut global_loc_helps = Vec::new(); + if !locator.crate_rejections.via_filename.is_empty() { + let mismatches = locator.crate_rejections.via_filename.iter(); + for CrateMismatch { path, .. } in mismatches { + global_loc_notes.push(format!( + "extern location for {} is of an unknown type: {}", + crate_name, + path.display(), + )); + global_loc_helps.push(format!( + "file name should be lib*.rlib or {}*.{}", + locator.dll_prefix, locator.dll_suffix + )); + } + panic!("!!!!! REVERT THIS COMMIT !!!!!"); + } + let mut found_crates = String::new(); + if !locator.crate_rejections.via_hash.is_empty() { let mismatches = locator.crate_rejections.via_hash.iter(); for CrateMismatch { path, .. } in mismatches { - msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display())); + found_crates.push_str(&format!( + "\ncrate `{}`: {}", + crate_name, + path.display() + )); } if let Some(r) = locator.root { for path in r.source.paths() { - msg.push_str(&format!("\ncrate `{}`: {}", r.name, path.display())); + found_crates.push_str(&format!( + "\ncrate `{}`: {}", + r.name, + path.display() + )); } } - err.note(&msg); - err - } else if !locator.crate_rejections.via_triple.is_empty() { - let mut err = struct_span_err!( - sess, + sess.emit_err(NewerCrateVersion { span, - E0461, - "couldn't find crate `{}` with expected target triple {}{}", - crate_name, - locator.triple, - add, - ); + crate_name: crate_name.to_string(), + add_info, + found_crates, + }); + } else if !locator.crate_rejections.via_triple.is_empty() { let mismatches = locator.crate_rejections.via_triple.iter(); for CrateMismatch { path, got } in mismatches { - msg.push_str(&format!( + found_crates.push_str(&format!( "\ncrate `{}`, target triple {}: {}", crate_name, got, path.display(), )); } - err.note(&msg); - err - } else if !locator.crate_rejections.via_kind.is_empty() { - let mut err = struct_span_err!( - sess, + sess.emit_err(NoCrateWithTriple { span, - E0462, - "found staticlib `{}` instead of rlib or dylib{}", - crate_name, - add, - ); - err.help("please recompile that crate using --crate-type lib"); + crate_name: crate_name.to_string(), + locator_triple: locator.triple.to_string(), + add_info, + found_crates, + }); + } else if !locator.crate_rejections.via_kind.is_empty() { let mismatches = locator.crate_rejections.via_kind.iter(); for CrateMismatch { path, .. } in mismatches { - msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display())); + found_crates.push_str(&format!( + "\ncrate `{}`: {}", + crate_name, + path.display() + )); } - err.note(&msg); - err - } else if !locator.crate_rejections.via_version.is_empty() { - let mut err = struct_span_err!( - sess, + sess.emit_err(FoundStaticlib { span, - E0514, - "found crate `{}` compiled by an incompatible version of rustc{}", - crate_name, - add, - ); - err.help(&format!( - "please recompile that crate using this compiler ({}) \ - (consider running `cargo clean` first)", - rustc_version(), - )); + crate_name: crate_name.to_string(), + add_info, + found_crates, + }); + } else if !locator.crate_rejections.via_version.is_empty() { let mismatches = locator.crate_rejections.via_version.iter(); for CrateMismatch { path, got } in mismatches { - msg.push_str(&format!( + found_crates.push_str(&format!( "\ncrate `{}` compiled by {}: {}", crate_name, got, path.display(), )); } - err.note(&msg); - err - } else if !locator.crate_rejections.via_invalid.is_empty() { - let mut err = struct_span_err!( - sess, + sess.emit_err(IncompatibleRustc { span, - E0786, - "found invalid metadata files for crate `{}`{}", - crate_name, - add, - ); + crate_name: crate_name.to_string(), + add_info, + found_crates, + rustc_version: rustc_version(), + }); + } else if !locator.crate_rejections.via_invalid.is_empty() { + let mut crate_rejections = Vec::new(); for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid { - err.note(&got); + crate_rejections.push(got); } - err + sess.emit_err(InvalidMetadataFiles { + span, + crate_name: crate_name.to_string(), + add_info, + crate_rejections, + }); } else { - let mut err = struct_span_err!( - sess, + sess.emit_err(CannotFindCrate { span, - E0463, - "can't find crate for `{}`{}", - crate_name, - add, - ); - - if (crate_name == sym::std || crate_name == sym::core) - && locator.triple != TargetTriple::from_triple(config::host_triple()) - { - if missing_core { - err.note(&format!( - "the `{}` target may not be installed", - locator.triple - )); - } else { - err.note(&format!( - "the `{}` target may not support the standard library", - locator.triple - )); - } - // NOTE: this suggests using rustup, even though the user may not have it installed. - // That's because they could choose to install it; or this may give them a hint which - // target they need to install from their distro. - if missing_core { - err.help(&format!( - "consider downloading the target with `rustup target add {}`", - locator.triple - )); - } - // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway. - // NOTE: this is a dummy span if `extern crate std` was injected by the compiler. - // If it's not a dummy, that means someone added `extern crate std` explicitly and `#![no_std]` won't help. - if !missing_core && span.is_dummy() { - let current_crate = - sess.opts.crate_name.as_deref().unwrap_or(""); - err.note(&format!( - "`std` is required by `{}` because it does not declare `#![no_std]`", - current_crate - )); - } - if sess.is_nightly_build() { - err.help("consider building the standard library from source with `cargo build -Zbuild-std`"); - } - } else if crate_name - == Symbol::intern(&sess.opts.unstable_opts.profiler_runtime) - { - err.note("the compiler may have been built without the profiler runtime"); - } else if crate_name.as_str().starts_with("rustc_") { - err.help( - "maybe you need to install the missing components with: \ - `rustup component add rust-src rustc-dev llvm-tools-preview`", - ); - } - err.span_label(span, "can't find crate"); - err - }; - - if !locator.crate_rejections.via_filename.is_empty() { - let mismatches = locator.crate_rejections.via_filename.iter(); - for CrateMismatch { path, .. } in mismatches { - err.note(&format!( - "extern location for {} is of an unknown type: {}", - crate_name, - path.display(), - )) - .help(&format!( - "file name should be lib*.rlib or {}*.{}", - locator.dll_prefix, locator.dll_suffix - )); - } + crate_name: crate_name.to_string(), + crate_name_symbol: crate_name, + add_info, + missing_core, + current_crate: sess + .opts + .crate_name + .clone() + .unwrap_or("".to_string()), + is_nightly_build: sess.is_nightly_build(), + profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), + locator_triple: locator.triple, + }); } - err } - CrateError::NonDylibPlugin(crate_name) => struct_span_err!( - sess, - span, - E0457, - "plugin `{}` only found in rlib format, but must be available in dylib format", - crate_name, - ), - }; - - diag.emit(); + CrateError::NonDylibPlugin(crate_name) => { + sess.emit_err(NoDylibPlugin { span, crate_name: crate_name.to_string() }); + } + } } } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index e8489232fbda6..dbaa2e9defa1a 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -1,7 +1,6 @@ use rustc_ast::{NestedMetaItem, CRATE_NODE_ID}; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; From 0d65819d529f222e47164f6c8132d8134909f2a4 Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Fri, 26 Aug 2022 14:39:59 -0600 Subject: [PATCH 19/23] respond to review feedback: mainly eliminate as many conversions as possible... - ... when creating diagnostics in rustc_metadata - use the error_code! macro - pass macro output to diag.code() - use fluent from within manual implementation of SessionDiagnostic - emit the untested errors in case they occur in the wild - stop panicking in the probably-not-dead code, add fixme to write test --- Cargo.lock | 1 + .../locales/en-US/metadata.ftl | 30 +++ compiler/rustc_errors/Cargo.toml | 5 +- compiler/rustc_errors/src/diagnostic.rs | 7 + compiler/rustc_metadata/src/creader.rs | 19 +- .../rustc_metadata/src/dependency_format.rs | 30 ++- compiler/rustc_metadata/src/errors.rs | 215 +++++++++--------- compiler/rustc_metadata/src/fs.rs | 27 +-- compiler/rustc_metadata/src/locator.rs | 102 ++++----- compiler/rustc_metadata/src/native_libs.rs | 18 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 6 +- 11 files changed, 234 insertions(+), 226 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 002d73be7d1de..0ce329ff07086 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3514,6 +3514,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", + "rustc_target", "serde", "serde_json", "termcolor", diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index e3e58cf8bed7e..dee01bcad4bbc 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -225,3 +225,33 @@ metadata_cannot_find_crate = metadata_no_dylib_plugin = plugin `{$crate_name}` only found in rlib format, but must be available in dylib format + +metadata_target_not_installed = + the `{$locator_triple}` target may not be installed + +metadata_target_no_std_support = + the `{$locator_triple}` target may not support the standard library + +metadata_consider_downloading_target = + consider downloading the target with `rustup target add {$locator_triple}` + +metadata_std_required = + `std` is required by `{$current_crate}` because it does not declare `#![no_std]` + +metadata_consider_building_std = + consider building the standard library from source with `cargo build -Zbuild-std` + +metadata_compiler_missing_profiler = + the compiler may have been built without the profiler runtime + +metadata_install_missing_components = + maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview` + +metadata_cant_find_crate = + can't find crate + +metadata_crate_location_unknown_type = + extern location for {$crate_name} is of an unknown type: {$path} + +metadata_lib_filename_form = + file name should be lib*.rlib or {dll_prefix}*.{dll_suffix} diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 36805aa874fe7..4d207fd17fb2d 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -15,13 +15,14 @@ rustc_macros = { path = "../rustc_macros" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } rustc_lint_defs = { path = "../rustc_lint_defs" } +rustc_target = { path = "../rustc_target" } unicode-width = "0.1.4" atty = "0.2" termcolor = "1.0" annotate-snippets = "0.9" termize = "0.1.1" -serde = { version = "1.0.125", features = ["derive"] } +serde = { version = "1.0.125", features = [ "derive" ] } serde_json = "1.0.59" [target.'cfg(windows)'.dependencies] -winapi = { version = "0.3", features = ["handleapi", "synchapi", "winbase"] } +winapi = { version = "0.3", features = [ "handleapi", "synchapi", "winbase" ] } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index f75e2596f361b..b569ef4fc2c91 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -10,6 +10,7 @@ use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_span::edition::LATEST_STABLE_EDITION; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol}; use rustc_span::{edition::Edition, Span, DUMMY_SP}; +use rustc_target::spec::PanicStrategy; use std::borrow::Cow; use std::fmt; use std::hash::{Hash, Hasher}; @@ -144,6 +145,12 @@ impl IntoDiagnosticArg for usize { } } +impl IntoDiagnosticArg for PanicStrategy { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string())) + } +} + impl<'source> Into> for DiagnosticArgValue<'source> { fn into(self) -> FluentValue<'source> { match self { diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index f9aa3733f6a37..edffec8ab55c4 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -750,13 +750,10 @@ impl<'a> CrateLoader<'a> { // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. if !data.is_panic_runtime() { - self.sess.emit_err(CrateNotPanicRuntime { crate_name: name.to_string() }); + self.sess.emit_err(CrateNotPanicRuntime { crate_name: name }); } if data.required_panic_strategy() != Some(desired_strategy) { - self.sess.emit_err(NoPanicStrategy { - crate_name: name.to_string(), - strategy: desired_strategy.desc().to_string(), - }); + self.sess.emit_err(NoPanicStrategy { crate_name: name, strategy: desired_strategy }); } self.cstore.injected_panic_runtime = Some(cnum); @@ -784,7 +781,7 @@ impl<'a> CrateLoader<'a> { // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.is_profiler_runtime() { - self.sess.emit_err(NotProfilerRuntime { crate_name: name.to_string() }); + self.sess.emit_err(NotProfilerRuntime { crate_name: name }); } } @@ -828,8 +825,8 @@ impl<'a> CrateLoader<'a> { match global_allocator { Some(other_crate) => { self.sess.emit_err(ConflictingGlobalAlloc { - crate_name: data.name().to_string(), - other_crate_name: other_crate.to_string(), + crate_name: data.name(), + other_crate_name: other_crate, }); } None => global_allocator = Some(data.name()), @@ -874,9 +871,9 @@ impl<'a> CrateLoader<'a> { let data = self.cstore.get_crate_data(dep); if needs_dep(&data) { self.sess.emit_err(NoTransitiveNeedsDep { - crate_name: self.cstore.get_crate_data(krate).name().to_string(), - needs_crate_name: what.to_string(), - deps_crate_name: data.name().to_string(), + crate_name: self.cstore.get_crate_data(krate).name(), + needs_crate_name: what, + deps_crate_name: data.name(), }); } } diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 5d1082acc0beb..9ad0099ad251b 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -140,7 +140,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { if src.rlib.is_some() { continue; } - sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum).to_string() }); + sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) }); } return Vec::new(); } @@ -224,10 +224,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { Linkage::Static => "rlib", _ => "dylib", }; - sess.emit_err(LibRequired { - crate_name: tcx.crate_name(cnum).to_string(), - kind: kind.to_string(), - }); + sess.emit_err(LibRequired { crate_name: tcx.crate_name(cnum), kind: kind }); } } } @@ -251,8 +248,7 @@ fn add_library( // This error is probably a little obscure, but I imagine that it // can be refined over time. if link2 != link || link == RequireStatic { - tcx.sess - .emit_err(CrateDepMultiple { crate_name: tcx.crate_name(cnum).to_string() }); + tcx.sess.emit_err(CrateDepMultiple { crate_name: tcx.crate_name(cnum) }); } } None => { @@ -347,8 +343,8 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { if tcx.is_panic_runtime(cnum) { if let Some((prev, _)) = panic_runtime { - let prev_name = tcx.crate_name(prev).to_string(); - let cur_name = tcx.crate_name(cnum).to_string(); + let prev_name = tcx.crate_name(prev); + let cur_name = tcx.crate_name(cnum); sess.emit_err(TwoPanicRuntimes { prev_name, cur_name }); } panic_runtime = Some(( @@ -370,8 +366,8 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { // our same strategy. if found_strategy != desired_strategy { sess.emit_err(BadPanicStrategy { - runtime: tcx.crate_name(runtime_cnum).to_string(), - strategy: desired_strategy.desc().to_string(), + runtime: tcx.crate_name(runtime_cnum), + strategy: desired_strategy, }); } @@ -390,17 +386,17 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { if let Some(found_strategy) = tcx.required_panic_strategy(cnum) && desired_strategy != found_strategy { sess.emit_err(RequiredPanicStrategy { - crate_name: tcx.crate_name(cnum).to_string(), - found_strategy: found_strategy.desc().to_string(), - desired_strategy: desired_strategy.desc().to_string() }); + crate_name: tcx.crate_name(cnum), + found_strategy, + desired_strategy}); } let found_drop_strategy = tcx.panic_in_drop_strategy(cnum); if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy { sess.emit_err(IncompatiblePanicInDropStrategy { - crate_name: tcx.crate_name(cnum).to_string(), - found_strategy: found_drop_strategy.desc().to_string(), - desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop.desc().to_string(), + crate_name: tcx.crate_name(cnum), + found_strategy: found_drop_strategy, + desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop, }); } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index d3f35ca8d164f..565c96917e2fc 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -1,59 +1,64 @@ -use std::path::PathBuf; +use std::{ + io::Error, + path::{Path, PathBuf}, +}; -use rustc_errors::{DiagnosticId, ErrorGuaranteed}; +use rustc_errors::{error_code, ErrorGuaranteed}; use rustc_macros::SessionDiagnostic; use rustc_session::{config, SessionDiagnostic}; use rustc_span::{sym, Span, Symbol}; -use rustc_target::spec::TargetTriple; +use rustc_target::spec::{PanicStrategy, TargetTriple}; + +use crate::locator::CrateFlavor; #[derive(SessionDiagnostic)] #[diag(metadata::rlib_required)] pub struct RlibRequired { - pub crate_name: String, + pub crate_name: Symbol, } #[derive(SessionDiagnostic)] #[diag(metadata::lib_required)] -pub struct LibRequired { - pub crate_name: String, - pub kind: String, +pub struct LibRequired<'a> { + pub crate_name: Symbol, + pub kind: &'a str, } #[derive(SessionDiagnostic)] #[diag(metadata::crate_dep_multiple)] #[help] pub struct CrateDepMultiple { - pub crate_name: String, + pub crate_name: Symbol, } #[derive(SessionDiagnostic)] #[diag(metadata::two_panic_runtimes)] pub struct TwoPanicRuntimes { - pub prev_name: String, - pub cur_name: String, + pub prev_name: Symbol, + pub cur_name: Symbol, } #[derive(SessionDiagnostic)] #[diag(metadata::bad_panic_strategy)] pub struct BadPanicStrategy { - pub runtime: String, - pub strategy: String, + pub runtime: Symbol, + pub strategy: PanicStrategy, } #[derive(SessionDiagnostic)] #[diag(metadata::required_panic_strategy)] pub struct RequiredPanicStrategy { - pub crate_name: String, - pub found_strategy: String, - pub desired_strategy: String, + pub crate_name: Symbol, + pub found_strategy: PanicStrategy, + pub desired_strategy: PanicStrategy, } #[derive(SessionDiagnostic)] #[diag(metadata::incompatible_panic_in_drop_strategy)] pub struct IncompatiblePanicInDropStrategy { - pub crate_name: String, - pub found_strategy: String, - pub desired_strategy: String, + pub crate_name: Symbol, + pub found_strategy: PanicStrategy, + pub desired_strategy: PanicStrategy, } #[derive(SessionDiagnostic)] @@ -129,11 +134,11 @@ pub struct FrameworkOnlyWindows { #[derive(SessionDiagnostic)] #[diag(metadata::unknown_link_kind, code = "E0458")] -pub struct UnknownLinkKind { +pub struct UnknownLinkKind<'a> { #[primary_span] #[label] pub span: Span, - pub kind: String, + pub kind: &'a str, } #[derive(SessionDiagnostic)] @@ -180,10 +185,10 @@ pub struct InvalidLinkModifier { #[derive(SessionDiagnostic)] #[diag(metadata::multiple_modifiers)] -pub struct MultipleModifiers { +pub struct MultipleModifiers<'a> { #[primary_span] pub span: Span, - pub modifier: String, + pub modifier: &'a str, } #[derive(SessionDiagnostic)] @@ -209,10 +214,10 @@ pub struct AsNeededCompatibility { #[derive(SessionDiagnostic)] #[diag(metadata::unknown_link_modifier)] -pub struct UnknownLinkModifier { +pub struct UnknownLinkModifier<'a> { #[primary_span] pub span: Span, - pub modifier: String, + pub modifier: &'a str, } #[derive(SessionDiagnostic)] @@ -250,20 +255,20 @@ pub struct LibFrameworkApple; #[derive(SessionDiagnostic)] #[diag(metadata::empty_renaming_target)] -pub struct EmptyRenamingTarget { - pub lib_name: String, +pub struct EmptyRenamingTarget<'a> { + pub lib_name: &'a str, } #[derive(SessionDiagnostic)] #[diag(metadata::renaming_no_link)] -pub struct RenamingNoLink { - pub lib_name: String, +pub struct RenamingNoLink<'a> { + pub lib_name: &'a str, } #[derive(SessionDiagnostic)] #[diag(metadata::multiple_renamings)] -pub struct MultipleRenamings { - pub lib_name: String, +pub struct MultipleRenamings<'a> { + pub lib_name: &'a str, } #[derive(SessionDiagnostic)] @@ -290,32 +295,32 @@ pub struct UnsupportedAbi { #[derive(SessionDiagnostic)] #[diag(metadata::fail_create_file_encoder)] pub struct FailCreateFileEncoder { - pub err: String, + pub err: Error, } #[derive(SessionDiagnostic)] #[diag(metadata::fail_seek_file)] pub struct FailSeekFile { - pub err: String, + pub err: Error, } #[derive(SessionDiagnostic)] #[diag(metadata::fail_write_file)] pub struct FailWriteFile { - pub err: String, + pub err: Error, } #[derive(SessionDiagnostic)] #[diag(metadata::crate_not_panic_runtime)] pub struct CrateNotPanicRuntime { - pub crate_name: String, + pub crate_name: Symbol, } #[derive(SessionDiagnostic)] #[diag(metadata::no_panic_strategy)] pub struct NoPanicStrategy { - pub crate_name: String, - pub strategy: String, + pub crate_name: Symbol, + pub strategy: PanicStrategy, } #[derive(SessionDiagnostic)] @@ -325,7 +330,7 @@ pub struct ProfilerBuiltinsNeedsCore; #[derive(SessionDiagnostic)] #[diag(metadata::not_profiler_runtime)] pub struct NotProfilerRuntime { - pub crate_name: String, + pub crate_name: Symbol, } #[derive(SessionDiagnostic)] @@ -341,8 +346,8 @@ pub struct NoMultipleGlobalAlloc { #[derive(SessionDiagnostic)] #[diag(metadata::conflicting_global_alloc)] pub struct ConflictingGlobalAlloc { - pub crate_name: String, - pub other_crate_name: String, + pub crate_name: Symbol, + pub other_crate_name: Symbol, } #[derive(SessionDiagnostic)] @@ -351,36 +356,36 @@ pub struct GlobalAllocRequired; #[derive(SessionDiagnostic)] #[diag(metadata::no_transitive_needs_dep)] -pub struct NoTransitiveNeedsDep { - pub crate_name: String, - pub needs_crate_name: String, - pub deps_crate_name: String, +pub struct NoTransitiveNeedsDep<'a> { + pub crate_name: Symbol, + pub needs_crate_name: &'a str, + pub deps_crate_name: Symbol, } #[derive(SessionDiagnostic)] #[diag(metadata::failed_write_error)] pub struct FailedWriteError { - pub filename: String, - pub err: String, + pub filename: PathBuf, + pub err: Error, } #[derive(SessionDiagnostic)] #[diag(metadata::failed_create_tempdir)] pub struct FailedCreateTempdir { - pub err: String, + pub err: Error, } #[derive(SessionDiagnostic)] #[diag(metadata::failed_create_file)] -pub struct FailedCreateFile { - pub filename: String, - pub err: String, +pub struct FailedCreateFile<'a> { + pub filename: &'a Path, + pub err: Error, } #[derive(SessionDiagnostic)] #[diag(metadata::failed_create_encoded_metadata)] pub struct FailedCreateEncodedMetadata { - pub err: String, + pub err: Error, } #[derive(SessionDiagnostic)] @@ -388,31 +393,31 @@ pub struct FailedCreateEncodedMetadata { pub struct NonAsciiName { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, } #[derive(SessionDiagnostic)] #[diag(metadata::extern_location_not_exist)] -pub struct ExternLocationNotExist { +pub struct ExternLocationNotExist<'a> { #[primary_span] pub span: Span, - pub crate_name: String, - pub location: String, + pub crate_name: Symbol, + pub location: &'a Path, } #[derive(SessionDiagnostic)] #[diag(metadata::extern_location_not_file)] -pub struct ExternLocationNotFile { +pub struct ExternLocationNotFile<'a> { #[primary_span] pub span: Span, - pub crate_name: String, - pub location: String, + pub crate_name: Symbol, + pub location: &'a Path, } -pub struct MultipleCandidates { +pub(crate) struct MultipleCandidates { pub span: Span, - pub flavor: String, - pub crate_name: String, + pub flavor: CrateFlavor, + pub crate_name: Symbol, pub candidates: Vec, } @@ -424,7 +429,7 @@ impl SessionDiagnostic<'_> for MultipleCandidates { let mut diag = sess.struct_err(rustc_errors::fluent::metadata::multiple_candidates); diag.set_arg("crate_name", self.crate_name); diag.set_arg("flavor", self.flavor); - diag.code(DiagnosticId::Error("E0465".into())); + diag.code(error_code!(E0465)); diag.set_span(self.span); for (i, candidate) in self.candidates.iter().enumerate() { diag.span_note(self.span, &format!("candidate #{}: {}", i + 1, candidate.display())); @@ -439,7 +444,7 @@ impl SessionDiagnostic<'_> for MultipleCandidates { pub struct MultipleMatchingCrates { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, pub candidates: String, } @@ -448,7 +453,7 @@ pub struct MultipleMatchingCrates { pub struct SymbolConflictsCurrent { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, } #[derive(SessionDiagnostic)] @@ -456,7 +461,7 @@ pub struct SymbolConflictsCurrent { pub struct SymbolConflictsOthers { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, } #[derive(SessionDiagnostic)] @@ -464,8 +469,8 @@ pub struct SymbolConflictsOthers { pub struct StableCrateIdCollision { #[primary_span] pub span: Span, - pub crate_name0: String, - pub crate_name1: String, + pub crate_name0: Symbol, + pub crate_name1: Symbol, } #[derive(SessionDiagnostic)] @@ -483,7 +488,7 @@ pub struct DlError { pub struct NewerCrateVersion { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, pub add_info: String, pub found_crates: String, } @@ -491,11 +496,11 @@ pub struct NewerCrateVersion { #[derive(SessionDiagnostic)] #[diag(metadata::no_crate_with_triple, code = "E0461")] #[note(metadata::found_crate_versions)] -pub struct NoCrateWithTriple { +pub struct NoCrateWithTriple<'a> { #[primary_span] pub span: Span, - pub crate_name: String, - pub locator_triple: String, + pub crate_name: Symbol, + pub locator_triple: &'a str, pub add_info: String, pub found_crates: String, } @@ -507,7 +512,7 @@ pub struct NoCrateWithTriple { pub struct FoundStaticlib { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, pub add_info: String, pub found_crates: String, } @@ -519,7 +524,7 @@ pub struct FoundStaticlib { pub struct IncompatibleRustc { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, pub add_info: String, pub found_crates: String, pub rustc_version: String, @@ -527,7 +532,7 @@ pub struct IncompatibleRustc { pub struct InvalidMetadataFiles { pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, pub add_info: String, pub crate_rejections: Vec, } @@ -540,7 +545,7 @@ impl SessionDiagnostic<'_> for InvalidMetadataFiles { let mut diag = sess.struct_err(rustc_errors::fluent::metadata::invalid_meta_files); diag.set_arg("crate_name", self.crate_name); diag.set_arg("add_info", self.add_info); - diag.code(DiagnosticId::Error("E0786".into())); + diag.code(error_code!(E0786)); diag.set_span(self.span); for crate_rejection in self.crate_rejections { diag.note(crate_rejection); @@ -551,8 +556,7 @@ impl SessionDiagnostic<'_> for InvalidMetadataFiles { pub struct CannotFindCrate { pub span: Span, - pub crate_name: String, - pub crate_name_symbol: Symbol, + pub crate_name: Symbol, pub add_info: String, pub missing_core: bool, pub current_crate: String, @@ -567,53 +571,41 @@ impl SessionDiagnostic<'_> for CannotFindCrate { sess: &'_ rustc_session::parse::ParseSess, ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { let mut diag = sess.struct_err(rustc_errors::fluent::metadata::cannot_find_crate); - diag.set_arg("crate_name", self.crate_name.clone()); + diag.set_arg("crate_name", self.crate_name); diag.set_arg("add_info", self.add_info); - diag.code(DiagnosticId::Error("E0463".into())); + diag.set_arg("locator_triple", self.locator_triple.triple()); + diag.code(error_code!(E0463)); diag.set_span(self.span); - // FIXME: Find a way to distill this logic down into the derived SessionDiagnostic form - if (self.crate_name_symbol == sym::std || self.crate_name_symbol == sym::core) + if (self.crate_name == sym::std || self.crate_name == sym::core) && self.locator_triple != TargetTriple::from_triple(config::host_triple()) { if self.missing_core { - diag.note(&format!("the `{}` target may not be installed", self.locator_triple)); + diag.note(rustc_errors::fluent::metadata::target_not_installed); } else { - diag.note(&format!( - "the `{}` target may not support the standard library", - self.locator_triple - )); + diag.note(rustc_errors::fluent::metadata::target_no_std_support); } // NOTE: this suggests using rustup, even though the user may not have it installed. // That's because they could choose to install it; or this may give them a hint which // target they need to install from their distro. if self.missing_core { - diag.help(&format!( - "consider downloading the target with `rustup target add {}`", - self.locator_triple - )); + diag.help(rustc_errors::fluent::metadata::consider_downloading_target); } // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway. // NOTE: this is a dummy span if `extern crate std` was injected by the compiler. // If it's not a dummy, that means someone added `extern crate std` explicitly and // `#![no_std]` won't help. if !self.missing_core && self.span.is_dummy() { - diag.note(&format!( - "`std` is required by `{}` because it does not declare `#![no_std]`", - self.current_crate - )); + diag.note(rustc_errors::fluent::metadata::std_required); } if self.is_nightly_build { - diag.help("consider building the standard library from source with `cargo build -Zbuild-std`"); + diag.help(rustc_errors::fluent::metadata::consider_building_std); } - } else if self.crate_name_symbol == self.profiler_runtime { - diag.note("the compiler may have been built without the profiler runtime"); - } else if self.crate_name.starts_with("rustc_") { - diag.help( - "maybe you need to install the missing components with: \ - `rustup component add rust-src rustc-dev llvm-tools-preview`", - ); + } else if self.crate_name == self.profiler_runtime { + diag.note(rustc_errors::fluent::metadata::compiler_missing_profiler); + } else if self.crate_name.as_str().starts_with("rustc_") { + diag.help(rustc_errors::fluent::metadata::install_missing_components); } - diag.span_label(self.span, "can't find crate"); + diag.span_label(self.span, rustc_errors::fluent::metadata::cant_find_crate); diag } } @@ -623,5 +615,22 @@ impl SessionDiagnostic<'_> for CannotFindCrate { pub struct NoDylibPlugin { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::crate_location_unknown_type)] +pub struct CrateLocationUnknownType<'a> { + #[primary_span] + pub span: Span, + pub path: &'a Path, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::lib_filename_form)] +pub struct LibFilenameForm<'a> { + #[primary_span] + pub span: Span, + pub dll_prefix: &'a str, + pub dll_suffix: &'a str, } diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index 67c18766c5959..f360a586476e7 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -26,11 +26,8 @@ pub fn emit_metadata(sess: &Session, metadata: &[u8], tmpdir: &MaybeTempDir) -> let out_filename = tmpdir.as_ref().join(METADATA_FILENAME); let result = fs::write(&out_filename, metadata); - if let Err(e) = result { - sess.emit_fatal(FailedWriteError { - filename: out_filename.display().to_string(), - err: e.to_string(), - }); + if let Err(err) = result { + sess.emit_fatal(FailedWriteError { filename: out_filename, err }); } out_filename @@ -71,7 +68,7 @@ pub fn encode_and_write_metadata( let metadata_tmpdir = TempFileBuilder::new() .prefix("rmeta") .tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new(""))) - .unwrap_or_else(|err| tcx.sess.emit_fatal(FailedCreateTempdir { err: err.to_string() })); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailedCreateTempdir { err })); let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps); let metadata_filename = metadata_tmpdir.as_ref().join(METADATA_FILENAME); @@ -79,11 +76,8 @@ pub fn encode_and_write_metadata( // This simplifies the creation of the output `out_filename` when requested. match metadata_kind { MetadataKind::None => { - std::fs::File::create(&metadata_filename).unwrap_or_else(|e| { - tcx.sess.emit_fatal(FailedCreateFile { - filename: metadata_filename.display().to_string(), - err: e.to_string(), - }); + std::fs::File::create(&metadata_filename).unwrap_or_else(|err| { + tcx.sess.emit_fatal(FailedCreateFile { filename: &metadata_filename, err }); }); } MetadataKind::Uncompressed | MetadataKind::Compressed => { @@ -98,11 +92,8 @@ pub fn encode_and_write_metadata( // this file always exists. let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata); let (metadata_filename, metadata_tmpdir) = if need_metadata_file { - if let Err(e) = non_durable_rename(&metadata_filename, &out_filename) { - tcx.sess.emit_fatal(FailedWriteError { - filename: out_filename.display().to_string(), - err: e.to_string(), - }); + if let Err(err) = non_durable_rename(&metadata_filename, &out_filename) { + tcx.sess.emit_fatal(FailedWriteError { filename: out_filename, err }); } if tcx.sess.opts.json_artifact_notifications { tcx.sess @@ -117,8 +108,8 @@ pub fn encode_and_write_metadata( // Load metadata back to memory: codegen may need to include it in object files. let metadata = - EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|e| { - tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err: e.to_string() }); + EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| { + tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err }); }); let need_metadata_module = metadata_kind == MetadataKind::Compressed; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 83c8756078ec4..5edad819e7e3c 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -214,10 +214,11 @@ use crate::creader::Library; use crate::errors::{ - CannotFindCrate, DlError, ExternLocationNotExist, ExternLocationNotFile, FoundStaticlib, - IncompatibleRustc, InvalidMetadataFiles, MultipleCandidates, MultipleMatchingCrates, - NewerCrateVersion, NoCrateWithTriple, NoDylibPlugin, NonAsciiName, StableCrateIdCollision, - SymbolConflictsCurrent, SymbolConflictsOthers, + CannotFindCrate, CrateLocationUnknownType, DlError, ExternLocationNotExist, + ExternLocationNotFile, FoundStaticlib, IncompatibleRustc, InvalidMetadataFiles, + LibFilenameForm, MultipleCandidates, MultipleMatchingCrates, NewerCrateVersion, + NoCrateWithTriple, NoDylibPlugin, NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent, + SymbolConflictsOthers, }; use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; @@ -226,7 +227,7 @@ use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; -use rustc_errors::FatalError; +use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg}; use rustc_session::config::{self, CrateType}; use rustc_session::cstore::{CrateSource, MetadataLoader}; use rustc_session::filesearch::FileSearch; @@ -238,6 +239,7 @@ use rustc_span::Span; use rustc_target::spec::{Target, TargetTriple}; use snap::read::FrameDecoder; +use std::borrow::Cow; use std::fmt::Write as _; use std::io::{Read, Result as IoResult, Write}; use std::path::{Path, PathBuf}; @@ -294,6 +296,16 @@ impl fmt::Display for CrateFlavor { } } +impl IntoDiagnosticArg for CrateFlavor { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + match self { + CrateFlavor::Rlib => DiagnosticArgValue::Str(Cow::Borrowed("rlib")), + CrateFlavor::Rmeta => DiagnosticArgValue::Str(Cow::Borrowed("rmeta")), + CrateFlavor::Dylib => DiagnosticArgValue::Str(Cow::Borrowed("dylib")), + } + } +} + impl<'a> CrateLocator<'a> { pub(crate) fn new( sess: &'a Session, @@ -946,29 +958,16 @@ impl CrateError { pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) { match self { CrateError::NonAsciiName(crate_name) => { - sess.emit_err(NonAsciiName { span, crate_name: crate_name.to_string() }); + sess.emit_err(NonAsciiName { span, crate_name }); } CrateError::ExternLocationNotExist(crate_name, loc) => { - sess.emit_err(ExternLocationNotExist { - span, - crate_name: crate_name.to_string(), - location: loc.display().to_string(), - }); + sess.emit_err(ExternLocationNotExist { span, crate_name, location: &loc }); } CrateError::ExternLocationNotFile(crate_name, loc) => { - sess.emit_err(ExternLocationNotFile { - span, - crate_name: crate_name.to_string(), - location: loc.display().to_string(), - }); + sess.emit_err(ExternLocationNotFile { span, crate_name, location: &loc }); } CrateError::MultipleCandidates(crate_name, flavor, candidates) => { - sess.emit_err(MultipleCandidates { - span, - flavor: flavor.to_string(), - crate_name: crate_name.to_string(), - candidates, - }); + sess.emit_err(MultipleCandidates { span, flavor: flavor, crate_name, candidates }); } CrateError::MultipleMatchingCrates(crate_name, libraries) => { let mut libraries: Vec<_> = libraries.into_values().collect(); @@ -998,27 +997,23 @@ impl CrateError { s }) .collect::(); - sess.emit_err(MultipleMatchingCrates { - span, - crate_name: crate_name.to_string(), - candidates, - }); + sess.emit_err(MultipleMatchingCrates { span, crate_name, candidates }); } CrateError::SymbolConflictsCurrent(root_name) => { - sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name.to_string() }); + sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name }); } CrateError::SymbolConflictsOthers(root_name) => { - sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name.to_string() }); + sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name }); } CrateError::StableCrateIdCollision(crate_name0, crate_name1) => { sess.emit_err(StableCrateIdCollision { span, - crate_name0: crate_name0.to_string(), - crate_name1: crate_name1.to_string(), + crate_name0: crate_name0, + crate_name1: crate_name1, }); } CrateError::DlOpen(s) | CrateError::DlSym(s) => { - sess.emit_err(DlError { span, err: s.to_string() }); + sess.emit_err(DlError { span, err: s }); } CrateError::LocatorCombined(locator) => { let crate_name = locator.crate_name; @@ -1026,24 +1021,17 @@ impl CrateError { None => String::new(), Some(r) => format!(" which `{}` depends on", r.name), }; - // FIXME: Is there any way to get these notes and helps onto every diagnostic in this - // huge branch arm without changing them all to manual implementations? - let mut global_loc_notes = Vec::new(); - let mut global_loc_helps = Vec::new(); + // FIXME: There are no tests for CrateLocationUnknownType or LibFilenameForm if !locator.crate_rejections.via_filename.is_empty() { let mismatches = locator.crate_rejections.via_filename.iter(); for CrateMismatch { path, .. } in mismatches { - global_loc_notes.push(format!( - "extern location for {} is of an unknown type: {}", - crate_name, - path.display(), - )); - global_loc_helps.push(format!( - "file name should be lib*.rlib or {}*.{}", - locator.dll_prefix, locator.dll_suffix - )); + sess.emit_err(CrateLocationUnknownType { span, path: &path }); + sess.emit_err(LibFilenameForm { + span, + dll_prefix: &locator.dll_prefix, + dll_suffix: &locator.dll_suffix, + }); } - panic!("!!!!! REVERT THIS COMMIT !!!!!"); } let mut found_crates = String::new(); if !locator.crate_rejections.via_hash.is_empty() { @@ -1066,7 +1054,7 @@ impl CrateError { } sess.emit_err(NewerCrateVersion { span, - crate_name: crate_name.to_string(), + crate_name: crate_name, add_info, found_crates, }); @@ -1082,8 +1070,8 @@ impl CrateError { } sess.emit_err(NoCrateWithTriple { span, - crate_name: crate_name.to_string(), - locator_triple: locator.triple.to_string(), + crate_name: crate_name, + locator_triple: locator.triple.triple(), add_info, found_crates, }); @@ -1096,12 +1084,7 @@ impl CrateError { path.display() )); } - sess.emit_err(FoundStaticlib { - span, - crate_name: crate_name.to_string(), - add_info, - found_crates, - }); + sess.emit_err(FoundStaticlib { span, crate_name, add_info, found_crates }); } else if !locator.crate_rejections.via_version.is_empty() { let mismatches = locator.crate_rejections.via_version.iter(); for CrateMismatch { path, got } in mismatches { @@ -1114,7 +1097,7 @@ impl CrateError { } sess.emit_err(IncompatibleRustc { span, - crate_name: crate_name.to_string(), + crate_name, add_info, found_crates, rustc_version: rustc_version(), @@ -1126,15 +1109,14 @@ impl CrateError { } sess.emit_err(InvalidMetadataFiles { span, - crate_name: crate_name.to_string(), + crate_name, add_info, crate_rejections, }); } else { sess.emit_err(CannotFindCrate { span, - crate_name: crate_name.to_string(), - crate_name_symbol: crate_name, + crate_name, add_info, missing_core, current_crate: sess @@ -1149,7 +1131,7 @@ impl CrateError { } } CrateError::NonDylibPlugin(crate_name) => { - sess.emit_err(NoDylibPlugin { span, crate_name: crate_name.to_string() }); + sess.emit_err(NoDylibPlugin { span, crate_name }); } } } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index dbaa2e9defa1a..19f64ef70c9c6 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -124,7 +124,7 @@ impl<'tcx> Collector<'tcx> { NativeLibKind::RawDylib } kind => { - sess.emit_err(UnknownLinkKind { span, kind: kind.to_string() }); + sess.emit_err(UnknownLinkKind { span, kind }); continue; } }; @@ -249,10 +249,7 @@ impl<'tcx> Collector<'tcx> { } let assign_modifier = |dst: &mut Option| { if dst.is_some() { - sess.emit_err(MultipleModifiers { - span, - modifier: modifier.to_string(), - }); + sess.emit_err(MultipleModifiers { span, modifier }); } else { *dst = Some(value); } @@ -287,10 +284,7 @@ impl<'tcx> Collector<'tcx> { } _ => { - sess.emit_err(UnknownLinkModifier { - span, - modifier: modifier.to_string(), - }); + sess.emit_err(UnknownLinkModifier { span, modifier }); } } } @@ -379,11 +373,11 @@ impl<'tcx> Collector<'tcx> { .filter_map(|lib| lib.name.as_ref()) .any(|n| n.as_str() == lib.name); if new_name.is_empty() { - self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: lib.name.clone() }); + self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: &lib.name }); } else if !any_duplicate { - self.tcx.sess.emit_err(RenamingNoLink { lib_name: lib.name.clone() }); + self.tcx.sess.emit_err(RenamingNoLink { lib_name: &lib.name }); } else if !renames.insert(&lib.name) { - self.tcx.sess.emit_err(MultipleRenamings { lib_name: lib.name.clone() }); + self.tcx.sess.emit_err(MultipleRenamings { lib_name: &lib.name }); } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 2b1f9f17a3c85..8f55fb59f0bf8 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2270,7 +2270,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { let mut encoder = opaque::FileEncoder::new(path) - .unwrap_or_else(|err| tcx.sess.emit_fatal(FailCreateFileEncoder { err: err.to_string() })); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailCreateFileEncoder { err })); encoder.emit_raw_bytes(METADATA_HEADER); // Will be filled with the root position after encoding everything. @@ -2315,10 +2315,10 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { // Encode the root position. let header = METADATA_HEADER.len(); file.seek(std::io::SeekFrom::Start(header as u64)) - .unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err: err.to_string() })); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err })); let pos = root.position.get(); file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8]) - .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err: err.to_string() })); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err })); // Return to the position where we are before writing the root position. file.seek(std::io::SeekFrom::Start(pos_before_seek)).unwrap(); From 30adfd6a17bd0d7c4d1302cc4a0f92962577de4a Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Sat, 27 Aug 2022 17:50:11 -0600 Subject: [PATCH 20/23] port 5 new diagnostics that appeared in master --- .../locales/en-US/metadata.ftl | 15 ++++++++ compiler/rustc_metadata/src/errors.rs | 36 +++++++++++++++++++ compiler/rustc_metadata/src/native_libs.rs | 36 +++++++++---------- 3 files changed, 67 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index dee01bcad4bbc..00067a1bf6ad7 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -255,3 +255,18 @@ metadata_crate_location_unknown_type = metadata_lib_filename_form = file name should be lib*.rlib or {dll_prefix}*.{dll_suffix} + +metadata_multiple_import_name_type = + multiple `import_name_type` arguments in a single `#[link]` attribute + +metadata_import_name_type_form = + import name type must be of the form `import_name_type = "string"` + +metadata_import_name_type_x86 = + import name type is only supported on x86 + +metadata_unknown_import_name_type = + unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated + +metadata_import_name_type_raw = + import name type can only be used with link kind `raw-dylib` diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 565c96917e2fc..18d0248333a51 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -634,3 +634,39 @@ pub struct LibFilenameForm<'a> { pub dll_prefix: &'a str, pub dll_suffix: &'a str, } + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_import_name_type)] +pub struct MultipleImportNameType { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::import_name_type_form)] +pub struct ImportNameTypeForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::import_name_type_x86)] +pub struct ImportNameTypeX86 { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unknown_import_name_type)] +pub struct UnknownImportNameType<'a> { + #[primary_span] + pub span: Span, + pub import_name_type: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::import_name_type_raw)] +pub struct ImportNameTypeRaw { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 19f64ef70c9c6..87b5e750f1cb1 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -13,13 +13,14 @@ use rustc_target::spec::abi::Abi; use crate::errors::{ AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, EmptyRenamingTarget, - FrameworkOnlyWindows, IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, - LinkCfgForm, LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, - LinkNameForm, LinkOrdinalRawDylib, LinkRequiresName, MultipleCfgs, MultipleKindsInLink, - MultipleLinkModifiers, MultipleModifiers, MultipleNamesInLink, MultipleRenamings, - MultipleWasmImport, NoLinkModOverride, RawDylibNoNul, RenamingNoLink, UnexpectedLinkArg, - UnknownLinkKind, UnknownLinkModifier, UnsupportedAbi, UnsupportedAbiI686, WasmImportForm, - WholeArchiveNeedsStatic, + FrameworkOnlyWindows, ImportNameTypeForm, ImportNameTypeRaw, ImportNameTypeX86, + IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, LinkCfgForm, + LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, LinkNameForm, + LinkOrdinalRawDylib, LinkRequiresName, MultipleCfgs, MultipleImportNameType, + MultipleKindsInLink, MultipleLinkModifiers, MultipleModifiers, MultipleNamesInLink, + MultipleRenamings, MultipleWasmImport, NoLinkModOverride, RawDylibNoNul, RenamingNoLink, + UnexpectedLinkArg, UnknownImportNameType, UnknownLinkKind, UnknownLinkModifier, UnsupportedAbi, + UnsupportedAbiI686, WasmImportForm, WholeArchiveNeedsStatic, }; pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec { @@ -178,18 +179,15 @@ impl<'tcx> Collector<'tcx> { } sym::import_name_type => { if import_name_type.is_some() { - let msg = "multiple `import_name_type` arguments in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleImportNameType { span: item.span() }); continue; } let Some(link_import_name_type) = item.value_str() else { - let msg = "import name type must be of the form `import_name_type = \"string\"`"; - sess.span_err(item.span(), msg); + sess.emit_err(ImportNameTypeForm { span: item.span() }); continue; }; if self.tcx.sess.target.arch != "x86" { - let msg = "import name type is only supported on x86"; - sess.span_err(item.span(), msg); + sess.emit_err(ImportNameTypeX86 { span: item.span() }); continue; } @@ -198,11 +196,10 @@ impl<'tcx> Collector<'tcx> { "noprefix" => PeImportNameType::NoPrefix, "undecorated" => PeImportNameType::Undecorated, import_name_type => { - let msg = format!( - "unknown import name type `{import_name_type}`, expected one of: \ - decorated, noprefix, undecorated" - ); - sess.span_err(item.span(), msg); + sess.emit_err(UnknownImportNameType { + span: item.span(), + import_name_type, + }); continue; } }; @@ -301,8 +298,7 @@ impl<'tcx> Collector<'tcx> { // Do this outside of the loop so that `import_name_type` can be specified before `kind`. if let Some((_, span)) = import_name_type { if kind != Some(NativeLibKind::RawDylib) { - let msg = "import name type can only be used with link kind `raw-dylib`"; - sess.span_err(span, msg); + sess.emit_err(ImportNameTypeRaw { span }); } } From f921f5626d1dcc08f2707ed2c22e22fd1ad678b7 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Wed, 31 Aug 2022 11:10:19 -0700 Subject: [PATCH 21/23] Use parent_iter instead of a find_parent_node loop --- compiler/rustc_middle/src/hir/map/mod.rs | 3 +++ .../src/check/generator_interior.rs | 20 +++++++------------ 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 8f7877392483f..6217bffb8f76c 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -291,6 +291,9 @@ impl<'hir> Map<'hir> { Some(def_kind) } + /// Finds the id of the parent node to this one. + /// + /// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`]. pub fn find_parent_node(self, id: HirId) -> Option { if id.local_id == ItemLocalId::from_u32(0) { Some(self.tcx.hir_owner_parent(id.owner)) diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index f73d498aabc23..2710606f91436 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -387,18 +387,6 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { ty.needs_drop(self.fcx.tcx, self.fcx.param_env) }; - let find_parent_expr = |mut hir_id| { - let hir = self.fcx.tcx.hir(); - hir_id = hir.find_parent_node(hir_id)?; - loop { - if let hir::Node::Expr(_) = self.fcx.tcx.hir().find(hir_id)? { - return Some(hir_id); - } else { - hir_id = hir.find_parent_node(hir_id)?; - } - } - }; - // Typically, the value produced by an expression is consumed by its parent in some way, // so we only have to check if the parent contains a yield (note that the parent may, for // example, store the value into a local variable, but then we already consider local @@ -421,7 +409,13 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { }) { self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id) } else { - let parent_expr = find_parent_expr(expr.hir_id); + let parent_expr = self + .fcx + .tcx + .hir() + .parent_iter(expr.hir_id) + .find(|(_, node)| matches!(node, hir::Node::Expr(_))) + .map(|(id, _)| id); debug!("parent_expr: {:?}", parent_expr); match parent_expr { Some(parent) => Some(Scope { id: parent.local_id, data: ScopeData::Node }), From a928255ab1c6a594faa15f93d912c1179ae354ea Mon Sep 17 00:00:00 2001 From: Matt Hamrick Date: Wed, 31 Aug 2022 13:21:47 -0700 Subject: [PATCH 22/23] Fix bad target name in Walkthrough Walkthrough currently say: ``` rustup target add aarch_64-fuchsia ``` but should say ``` rustup target add aarch64-fuchsia ``` --- src/doc/rustc/src/platform-support/fuchsia.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index c2a1613f288c5..94373b01cc469 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -79,7 +79,7 @@ the following commands: ```sh rustup target add x86_64-fuchsia -rustup target add aarch_64-fuchsia +rustup target add aarch64-fuchsia ``` After installing our Fuchsia targets, we can now compile a Rust binary that targets From d8b572b820e2c1b59a26d28fc2c6234e34aedc6d Mon Sep 17 00:00:00 2001 From: Andrew Pollack Date: Wed, 31 Aug 2022 23:49:48 +0000 Subject: [PATCH 23/23] Tweaks to fuchsia doc walkthrough --- src/doc/rustc/src/platform-support/fuchsia.md | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index c2a1613f288c5..10d12f88454d1 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -125,13 +125,20 @@ during compilation: [target.x86_64-fuchsia] rustflags = [ - "-Lnative", "/arch/x64/sysroot/lib", - "-Lnative", "/arch/x64/lib" + "-Lnative=/arch/x64/lib", + "-Lnative=/arch/x64/sysroot/lib" ] ``` *Note: Make sure to fill out `` with the path to the downloaded [Fuchsia SDK].* +These options configure the following: + +* `-Lnative=${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from + the SDK +* `-Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia kernel + libraries from the SDK + In total, our new project will look like: **Current directory structure** @@ -368,6 +375,7 @@ language called CML. The Fuchsia devsite contains an [overview of CML] and a } ``` +**Current directory structure** ```txt hello_fuchsia/ ┗━ pkg/ @@ -386,6 +394,9 @@ ${SDK_PATH}/tools/${ARCH}/cmc compile \ -o pkg/meta/hello_fuchsia.cm ``` +*Note: `--includepath` tells the compiler where to look for `include`s from our CML. +In our case, we're only using `syslog/client.shard.cml`.* + **Current directory structure** ```txt hello_fuchsia/ @@ -397,19 +408,16 @@ hello_fuchsia/ ┗━ hello_fuchsia.cml ``` -*Note: `--includepath` tells the compiler where to look for `include`s from our CML. -In our case, we're only using `syslog/client.shard.cml`.* - ### Building a Fuchsia package Next, we'll build a package manifest as defined by our manifest: ```sh ${SDK_PATH}/tools/${ARCH}/pm \ - -o hello_fuchsia_manifest \ + -o pkg/hello_fuchsia_manifest \ -m pkg/hello_fuchsia.manifest \ build \ - -output-package-manifest hello_fuchsia_package_manifest + -output-package-manifest pkg/hello_fuchsia_package_manifest ``` This will produce `pkg/hello_fuchsia_manifest/` which is a package manifest we can @@ -469,15 +477,15 @@ We can publish our new package to that repository with: ```sh ${SDK_PATH}/tools/${ARCH}/pm publish \ - -repo repo \ - -lp -f <(echo "hello_fuchsia_package_manifest") + -repo pkg/repo \ + -lp -f <(echo "pkg/hello_fuchsia_package_manifest") ``` Then we can add the repository to `ffx`'s package server as `hello-fuchsia` using: ```sh ${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm \ - repo \ + pkg/repo \ -r hello-fuchsia ```