diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 3be6dd5af75ac..83fe2a2df892f 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -400,6 +400,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 @@ -495,7 +498,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), @@ -577,6 +580,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(), @@ -1000,20 +1004,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 @@ -1100,6 +1104,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/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/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; diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs index 12f0fe9c3c3a9..1ee69ff9cb285 100644 --- a/library/panic_unwind/src/emcc.rs +++ b/library/panic_unwind/src/emcc.rs @@ -105,15 +105,19 @@ 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, - 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 { - __gxx_personality_v0(version, actions, exception_class, exception_object, context) + core::intrinsics::abort() } extern "C" { @@ -125,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; } 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(()) } 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 + diff --git a/src/test/ui/hrtb/hrtb-just-for-static.rs b/src/test/ui/hrtb/hrtb-just-for-static.rs index ffafdce2a6c83..8fb4218f8a409 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.rs +++ b/src/test/ui/hrtb/hrtb-just-for-static.rs @@ -24,7 +24,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>() 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() {}