about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-06-10 09:05:50 +0000
committerbors <bors@rust-lang.org>2022-06-10 09:05:50 +0000
commitf19ccc2e8dab09e542d4c5a3ec14c7d5bce8d50e (patch)
tree4bb9736aa9f8bbc35b256aafcbf7c07e1c2402f3
parent3dea0033f7f40fc3a96b728cb2095da91135f0a4 (diff)
parent9d25bc37446529038255f92c2c461a37d227bb9e (diff)
downloadrust-f19ccc2e8dab09e542d4c5a3ec14c7d5bce8d50e.tar.gz
rust-f19ccc2e8dab09e542d4c5a3ec14c7d5bce8d50e.zip
Auto merge of #97939 - JohnTitor:rollup-79pxupb, r=JohnTitor
Rollup of 6 pull requests

Successful merges:

 - #97718 (Fix `delayed_good_path_bug` ice for expected diagnostics (RFC 2383))
 - #97876 (update docs for `std::future::IntoFuture`)
 - #97888 (Don't use __gxx_personality_v0 in panic_unwind on emscripten target)
 - #97922 (Remove redundant calls to reserve in impl Write for VecDeque)
 - #97927 (Do not introduce bindings for types and consts in HRTB.)
 - #97937 (Fix a typo in `test/ui/hrtb/hrtb-just-for-static.rs`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_errors/src/lib.rs29
-rw-r--r--compiler/rustc_resolve/src/late.rs7
-rw-r--r--library/core/src/future/into_future.rs119
-rw-r--r--library/panic_unwind/src/emcc.rs23
-rw-r--r--library/std/src/io/impls.rs2
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs7
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr14
-rw-r--r--src/test/ui/hrtb/hrtb-just-for-static.rs2
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs8
9 files changed, 182 insertions, 29 deletions
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 3be6dd5af75..83fe2a2df89 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -400,6 +400,9 @@ struct HandlerInner {
     emitter: Box<dyn Emitter + sync::Send>,
     delayed_span_bugs: Vec<Diagnostic>,
     delayed_good_path_bugs: Vec<DelayedDiagnostic>,
+    /// 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 771eeee965b..45a5adb90cf 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 8014dacdd98..d22094130ad 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<Self::Output>;
+///
+///     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: 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<Output = Self::Output>;
 
     /// 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 12f0fe9c3c3..1ee69ff9cb2 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 0ca58efe1fe..95072547302 100644
--- a/library/std/src/io/impls.rs
+++ b/library/std/src/io/impls.rs
@@ -441,14 +441,12 @@ impl<A: Allocator> Read for VecDeque<u8, A> {
 impl<A: Allocator> Write for VecDeque<u8, A> {
     #[inline]
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        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 00000000000..1a9bb252340
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs
@@ -0,0 +1,7 @@
+fn a() where for<T> T: Copy {}
+//~^ ERROR only lifetime parameters can be used in this context
+
+fn b() where for<const C: usize> [(); 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 00000000000..f31aa554634
--- /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> T: Copy {}
+   |                  ^
+
+error: only lifetime parameters can be used in this context
+  --> $DIR/hrtb-wrong-kind.rs:4:24
+   |
+LL | fn b() where for<const C: usize> [(); 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 ffafdce2a6c..8fb4218f8a4 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::<StaticInt>() //~ 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 00000000000..912e831d88a
--- /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<T: Drop>() {
+}
+
+fn main() {}