From 157e68d01bf5b5762f739299dcb7bbf3e12d5031 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sat, 4 Jun 2022 00:43:24 +0200 Subject: [PATCH 1/9] Fix `delayed_good_path_bug` ice for expected diagnostics (RFC 2383) --- compiler/rustc_errors/src/lib.rs | 29 +++++++++++-------- .../avoid_delayed_good_path_ice.rs | 8 +++++ 2 files changed, 25 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index fb02f1d68ebc9..8cce49971489e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -401,6 +401,9 @@ struct HandlerInner { emitter: Box, delayed_span_bugs: Vec, delayed_good_path_bugs: Vec, + /// This flag indicates that an expected diagnostic was emitted and suppressed. + /// This is used for the `delayed_good_path_bugs` check. + suppressed_expected_diag: bool, /// This set contains the `DiagnosticId` of all emitted diagnostics to avoid /// emitting the same diagnostic with extended help (`--teach`) twice, which @@ -496,7 +499,7 @@ impl Drop for HandlerInner { // instead of "require some error happened". Sadly that isn't ideal, as // lints can be `#[allow]`'d, potentially leading to this triggering. // Also, "good path" should be replaced with a better naming. - if !self.has_any_message() { + if !self.has_any_message() && !self.suppressed_expected_diag { let bugs = std::mem::replace(&mut self.delayed_good_path_bugs, Vec::new()); self.flush_delayed( bugs.into_iter().map(DelayedDiagnostic::decorate), @@ -578,6 +581,7 @@ impl Handler { emitter, delayed_span_bugs: Vec::new(), delayed_good_path_bugs: Vec::new(), + suppressed_expected_diag: false, taught_diagnostics: Default::default(), emitted_diagnostic_codes: Default::default(), emitted_diagnostics: Default::default(), @@ -1001,20 +1005,20 @@ impl Handler { let mut inner = self.inner.borrow_mut(); let diags = std::mem::take(&mut inner.unstable_expect_diagnostics); inner.check_unstable_expect_diagnostics = true; - if diags.is_empty() { - return; - } - for mut diag in diags.into_iter() { - diag.update_unstable_expectation_id(unstable_to_stable); + if !diags.is_empty() { + inner.suppressed_expected_diag = true; + for mut diag in diags.into_iter() { + diag.update_unstable_expectation_id(unstable_to_stable); - let stable_id = diag - .level - .get_expectation_id() - .expect("all diagnostics inside `unstable_expect_diagnostics` must have a `LintExpectationId`"); - inner.fulfilled_expectations.insert(stable_id); + let stable_id = diag + .level + .get_expectation_id() + .expect("all diagnostics inside `unstable_expect_diagnostics` must have a `LintExpectationId`"); + inner.fulfilled_expectations.insert(stable_id); - (*TRACK_DIAGNOSTICS)(&diag); + (*TRACK_DIAGNOSTICS)(&diag); + } } inner @@ -1101,6 +1105,7 @@ impl HandlerInner { (*TRACK_DIAGNOSTICS)(diagnostic); if let Level::Expect(expectation_id) = diagnostic.level { + self.suppressed_expected_diag = true; self.fulfilled_expectations.insert(expectation_id); return None; } else if diagnostic.level == Allow { diff --git a/src/test/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs b/src/test/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs new file mode 100644 index 0000000000000..912e831d88a7d --- /dev/null +++ b/src/test/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs @@ -0,0 +1,8 @@ +// check-pass +#![feature(lint_reasons)] + +#[expect(drop_bounds)] +fn trigger_rustc_lints() { +} + +fn main() {} From a4c455080cddec67086adfbb3b999bbcccfaffa9 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts <2467194+yoshuawuyts@users.noreply.github.com> Date: Wed, 8 Jun 2022 13:15:50 +0200 Subject: [PATCH 2/9] update docs for `std::future::IntoFuture` --- library/core/src/future/into_future.rs | 119 +++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/library/core/src/future/into_future.rs b/library/core/src/future/into_future.rs index 8014dacdd98da..d22094130ad9a 100644 --- a/library/core/src/future/into_future.rs +++ b/library/core/src/future/into_future.rs @@ -1,6 +1,109 @@ use crate::future::Future; /// Conversion into a `Future`. +/// +/// By implementing `Intofuture` for a type, you define how it will be +/// converted to a future. +/// +/// # `.await` desugaring +/// +/// The `.await` keyword desugars into a call to `IntoFuture::into_future` +/// first before polling the future to completion. `IntoFuture` is implemented +/// for all `T: Future` which means the `into_future` method will be available +/// on all futures. +/// +/// ```no_run +/// #![feature(into_future)] +/// +/// use std::future::IntoFuture; +/// +/// # async fn foo() { +/// let v = async { "meow" }; +/// let mut fut = v.into_future(); +/// assert_eq!("meow", fut.await); +/// # } +/// ``` +/// +/// # Async builders +/// +/// When implementing futures manually there will often be a choice between +/// implementing `Future` or `IntoFuture` for a type. Implementing `Future` is a +/// good choice in most cases. But implementing `IntoFuture` is most useful when +/// implementing "async builder" types, which allows the type to be modified +/// multiple times before being `.await`ed. +/// +/// ```rust +/// #![feature(into_future)] +/// +/// use std::future::{ready, Ready, IntoFuture}; +/// +/// /// Eventually multiply two numbers +/// pub struct Multiply { +/// num: u16, +/// factor: u16, +/// } +/// +/// impl Multiply { +/// /// Construct a new instance of `Multiply`. +/// pub fn new(num: u16, factor: u16) -> Self { +/// Self { num, factor } +/// } +/// +/// /// Set the number to multiply by the factor. +/// pub fn number(mut self, num: u16) -> Self { +/// self.num = num; +/// self +/// } +/// +/// /// Set the factor to multiply the number with. +/// pub fn factor(mut self, factor: u16) -> Self { +/// self.factor = factor; +/// self +/// } +/// } +/// +/// impl IntoFuture for Multiply { +/// type Output = u16; +/// type IntoFuture = Ready; +/// +/// fn into_future(self) -> Self::IntoFuture { +/// ready(self.num * self.factor) +/// } +/// } +/// +/// // NOTE: Rust does not yet have an `async fn main` function, that functionality +/// // currently only exists in the ecosystem. +/// async fn run() { +/// let num = Multiply::new(0, 0) // initialize the builder to number: 0, factor: 0 +/// .number(2) // change the number to 2 +/// .factor(2) // change the factor to 2 +/// .await; // convert to future and .await +/// +/// assert_eq!(num, 4); +/// } +/// ``` +/// +/// # Usage in trait bounds +/// +/// Using `IntoFuture` in trait bounds allows a function to be generic over both +/// `Future` and `IntoFuture`. This is convenient for users of the function, so +/// when they are using it they don't have to make an extra call to +/// `IntoFuture::into_future` to obtain an instance of `Future`: +/// +/// ```rust +/// #![feature(into_future)] +/// +/// use std::future::IntoFuture; +/// +/// /// Convert the output of a future to a string. +/// async fn fut_to_string(fut: Fut) -> String +/// where +/// Fut: IntoFuture, +/// Fut::Output: std::fmt::Debug, +/// { +/// format!("{:?}", fut.await) +/// } +/// ``` #[unstable(feature = "into_future", issue = "67644")] pub trait IntoFuture { /// The output that the future will produce on completion. @@ -12,6 +115,22 @@ pub trait IntoFuture { type IntoFuture: Future; /// Creates a future from a value. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ```no_run + /// #![feature(into_future)] + /// + /// use std::future::IntoFuture; + /// + /// # async fn foo() { + /// let v = async { "meow" }; + /// let mut fut = v.into_future(); + /// assert_eq!("meow", fut.await); + /// # } + /// ``` #[unstable(feature = "into_future", issue = "67644")] #[lang = "into_future"] fn into_future(self) -> Self::IntoFuture; From 2ecbdc1b3223eb9acda60014946738cd8e87f7e5 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 8 Jun 2022 10:04:02 -0700 Subject: [PATCH 3/9] Don't use __gxx_personality_v0 in panic_unwind on emscripten target This resolves #85821. See also the discussion here: https://github.com/emscripten-core/emscripten/issues/17128 The consensus seems to be that rust_eh_personality is never invoked. I patched __gxx_personality_v0 to log invocations and then ran various panic tests and it was never called, so this analysis matches what seems to happen in practice. This replaces the definition with an abort, modeled on the structured exception handling implementation. --- library/panic_unwind/src/emcc.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs index 12f0fe9c3c3a9..e3a32a5581eaf 100644 --- a/library/panic_unwind/src/emcc.rs +++ b/library/panic_unwind/src/emcc.rs @@ -105,6 +105,11 @@ extern "C" fn exception_cleanup(ptr: *mut libc::c_void) -> *mut libc::c_void { } } + +// This is required by the compiler to exist (e.g., it's a lang item), but it's +// never actually called by the compiler. Emscripten EH doesn't use a +// personality function at all, it instead uses __cxa_find_matching_catch. +// Wasm error handling would use __gxx_personality_wasm0. #[lang = "eh_personality"] unsafe extern "C" fn rust_eh_personality( version: c_int, @@ -113,7 +118,7 @@ unsafe extern "C" fn rust_eh_personality( exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, ) -> uw::_Unwind_Reason_Code { - __gxx_personality_v0(version, actions, exception_class, exception_object, context) + core::intrinsics::abort() } extern "C" { From 0ec3174e3ea682aac2633b38e75db0e94eabe5c9 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 8 Jun 2022 10:25:18 -0700 Subject: [PATCH 4/9] Fix formatter --- library/panic_unwind/src/emcc.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs index e3a32a5581eaf..790aacdbe455d 100644 --- a/library/panic_unwind/src/emcc.rs +++ b/library/panic_unwind/src/emcc.rs @@ -105,7 +105,6 @@ extern "C" fn exception_cleanup(ptr: *mut libc::c_void) -> *mut libc::c_void { } } - // This is required by the compiler to exist (e.g., it's a lang item), but it's // never actually called by the compiler. Emscripten EH doesn't use a // personality function at all, it instead uses __cxa_find_matching_catch. From 46a3f0feb6bee316a682bd8b62d3a0a0f2647619 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 8 Jun 2022 16:31:21 -0700 Subject: [PATCH 5/9] Remove __gxx_personality_v0 declaration --- library/panic_unwind/src/emcc.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs index 790aacdbe455d..c458af10aad19 100644 --- a/library/panic_unwind/src/emcc.rs +++ b/library/panic_unwind/src/emcc.rs @@ -129,11 +129,4 @@ extern "C" { tinfo: *const TypeInfo, dest: extern "C" fn(*mut libc::c_void) -> *mut libc::c_void, ) -> !; - fn __gxx_personality_v0( - version: c_int, - actions: uw::_Unwind_Action, - exception_class: uw::_Unwind_Exception_Class, - exception_object: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context, - ) -> uw::_Unwind_Reason_Code; } From d2d205d0a87861aaa2ce3a39a65afc35a2beb55a Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Thu, 9 Jun 2022 09:50:26 -0700 Subject: [PATCH 6/9] Add underscores to rust_eh_personality arguments to mark them as unused --- library/panic_unwind/src/emcc.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs index c458af10aad19..1ee69ff9cb285 100644 --- a/library/panic_unwind/src/emcc.rs +++ b/library/panic_unwind/src/emcc.rs @@ -111,11 +111,11 @@ extern "C" fn exception_cleanup(ptr: *mut libc::c_void) -> *mut libc::c_void { // Wasm error handling would use __gxx_personality_wasm0. #[lang = "eh_personality"] unsafe extern "C" fn rust_eh_personality( - version: c_int, - actions: uw::_Unwind_Action, - exception_class: uw::_Unwind_Exception_Class, - exception_object: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context, + _version: c_int, + _actions: uw::_Unwind_Action, + _exception_class: uw::_Unwind_Exception_Class, + _exception_object: *mut uw::_Unwind_Exception, + _context: *mut uw::_Unwind_Context, ) -> uw::_Unwind_Reason_Code { core::intrinsics::abort() } From c71e73eb61b3f48b3ea22ba66d24d03b1e418074 Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Thu, 9 Jun 2022 19:10:09 +0200 Subject: [PATCH 7/9] Remove redundant calls to reserve in impl Write for VecDeque --- library/std/src/io/impls.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index 0ca58efe1fe2f..95072547302eb 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -441,14 +441,12 @@ impl Read for VecDeque { impl Write for VecDeque { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { - self.reserve(buf.len()); self.extend(buf); Ok(buf.len()) } #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - self.reserve(buf.len()); self.extend(buf); Ok(()) } From 4d871a25bf96e577992218ac69b449e3648166be Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 9 Jun 2022 21:30:18 +0200 Subject: [PATCH 8/9] Do not introduce bindings for types and consts in HRTB. --- compiler/rustc_resolve/src/late.rs | 7 ++++++- .../ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs | 7 +++++++ .../hrtb-wrong-kind.stderr | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 771eeee965bb8..45a5adb90cfd2 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1981,7 +1981,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { continue; } }; - let res = Res::Def(def_kind, def_id.to_def_id()); + + let res = match kind { + ItemRibKind(..) | AssocItemRibKind => Res::Def(def_kind, def_id.to_def_id()), + NormalRibKind => Res::Err, + _ => bug!("Unexpected rib kind {:?}", kind), + }; self.r.record_partial_res(param.id, PartialRes::new(res)); rib.bindings.insert(ident, res); } diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs new file mode 100644 index 0000000000000..1a9bb252340a6 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs @@ -0,0 +1,7 @@ +fn a() where for T: Copy {} +//~^ ERROR only lifetime parameters can be used in this context + +fn b() where for [(); C]: Copy {} +//~^ ERROR only lifetime parameters can be used in this context + +fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr b/src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr new file mode 100644 index 0000000000000..f31aa55463470 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr @@ -0,0 +1,14 @@ +error: only lifetime parameters can be used in this context + --> $DIR/hrtb-wrong-kind.rs:1:18 + | +LL | fn a() where for T: Copy {} + | ^ + +error: only lifetime parameters can be used in this context + --> $DIR/hrtb-wrong-kind.rs:4:24 + | +LL | fn b() where for [(); C]: Copy {} + | ^ + +error: aborting due to 2 previous errors + From a0985fc20cac2e193d87425d1341bf75c535c96a Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Fri, 10 Jun 2022 13:44:21 +0900 Subject: [PATCH 9/9] fix a typo --- src/test/ui/hrtb/hrtb-just-for-static.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/hrtb/hrtb-just-for-static.rs b/src/test/ui/hrtb/hrtb-just-for-static.rs index dc70609c16841..ef7bba536f528 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.rs +++ b/src/test/ui/hrtb/hrtb-just-for-static.rs @@ -28,7 +28,7 @@ fn give_static() { want_hrtb::() //~ ERROR } -// AnyInt implements Foo<&'a isize> for any 'a, so it is a match. +// &'a u32 only implements Foo<&'a isize> for specific 'a, so it is an error. impl<'a> Foo<&'a isize> for &'a u32 { } fn give_some<'a>() { want_hrtb::<&'a u32>()