From 3b2b5b2914d40aa011d189bfe546084cdee53dbe Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Sun, 24 Jan 2021 16:43:54 -0800 Subject: [PATCH 01/21] Remove P: Unpin bound on impl Future for Pin The `Unpin` bound was originally added in #56939 following the recommendation of @withoutboats in https://github.com/rust-lang/rust/issues/55766#issue-378417538 That comment does not give explicit justification for why the bound should be added. The relevant context was: > [ ] Remove `impl

Unpin for Pin

` > > This impl is not justified by our standard justification for unpin > impls: there is no pointer direction between `Pin

` and `P`. Its > usefulness is covered by the impls for pointers themselves. > > This futures impl (link to the impl changed in this PR) will need to > change to add a `P: Unpin` bound. The decision to remove the unconditional impl of `Unpin for Pin` is sound (these days there is just an auto-impl for when `P: Unpin`). But, I think the decision to also add the `Unpin` bound for `impl Future` may have been unnecessary. Or if that's not the case, I'd be very interested to have the argument for why written down somewhere. The bound _appears_ to not be needed, since the presence of a `Pin

` should indicate that it's safe to project to `Pin<&mut P::Target>` just like for `Pin::as_mut`. --- library/core/src/future/future.rs | 4 ++-- library/core/src/lib.rs | 1 + library/core/src/pin.rs | 38 +++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs index e9a99ddb6b1bd..5a07c4ab22f3b 100644 --- a/library/core/src/future/future.rs +++ b/library/core/src/future/future.rs @@ -111,11 +111,11 @@ impl Future for &mut F { #[stable(feature = "futures_api", since = "1.36.0")] impl

Future for Pin

where - P: Unpin + ops::DerefMut, + P: ops::DerefMut, { type Output = <

::Target as Future>::Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - Pin::get_mut(self).as_mut().poll(cx) + ::poll(self.as_deref_mut(), cx) } } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index f47ad7e6bc214..07424e18e4e2b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -127,6 +127,7 @@ #![feature(no_core)] #![feature(auto_traits)] #![cfg_attr(bootstrap, feature(or_patterns))] +#![feature(pin_deref_mut)] #![feature(prelude_import)] #![cfg_attr(not(bootstrap), feature(ptr_metadata))] #![feature(repr_simd, platform_intrinsics)] diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index b2de0e16a17bb..bc562153713be 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -793,6 +793,44 @@ impl Pin<&'static T> { } } +impl<'a, P: DerefMut> Pin<&'a mut Pin

> { + /// Gets a pinned mutable reference from this nested pinned pointer. + /// + /// This is a generic method to go from `Pin<&mut Pin>>` to `Pin<&mut T>`. It is + /// safe because the existence of a `Pin>` ensures that the pointee, `T`, cannot + /// move in the future, and this method does not enable the pointee to move. "Malicious" + /// implementations of `Pointer::DerefMut` are likewise ruled out by the contract of + /// `Pin::new_unchecked`. + #[unstable(feature = "pin_deref_mut", issue = "none")] + #[inline(always)] + pub fn as_deref_mut(self) -> Pin<&'a mut P::Target> { + // SAFETY: What we're asserting here is that going from + // + // Pin<&mut Pin

> + // + // to + // + // Pin<&mut P::Target> + // + // is safe. + // + // We need to ensure that two things hold for that to be the case: + // + // 1) Once we give out a `Pin<&mut P::Target>`, an `&mut P::Target` will not be given out. + // 2) By giving out a `Pin<&mut P::Target>`, we do not risk of violating `Pin<&mut Pin

>` + // + // The existence of `Pin

` is sufficient to guarantee #1: since we already have a + // `Pin

`, it must already uphold the pinning guarantees, which must mean that + // `Pin<&mut P::Target>` does as well, since `Pin::as_mut` is safe. We do not have to rely + // on the fact that P is _also_ pinned. + // + // For #2, we need to ensure that code given a `Pin<&mut P::Target>` cannot cause the + // `Pin

` to move? That is not possible, since `Pin<&mut P::Target>` no longer retains + // any access to the `P` itself, much less the `Pin

`. + unsafe { self.get_unchecked_mut() }.as_mut() + } +} + impl Pin<&'static mut T> { /// Get a pinned mutable reference from a static mutable reference. /// From b5e5a182caa6efb7359978a6ff596f403cb4c099 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Tue, 15 Jun 2021 20:47:43 -0400 Subject: [PATCH 02/21] Update library/core/src/pin.rs Co-authored-by: Ralf Jung --- library/core/src/pin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 7eb2029013e62..85411bac946a4 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -808,7 +808,7 @@ impl<'a, P: DerefMut> Pin<&'a mut Pin

> { /// This is a generic method to go from `Pin<&mut Pin>>` to `Pin<&mut T>`. It is /// safe because the existence of a `Pin>` ensures that the pointee, `T`, cannot /// move in the future, and this method does not enable the pointee to move. "Malicious" - /// implementations of `Pointer::DerefMut` are likewise ruled out by the contract of + /// implementations of `P::DerefMut` are likewise ruled out by the contract of /// `Pin::new_unchecked`. #[unstable(feature = "pin_deref_mut", issue = "none")] #[inline(always)] From cf402921222bd6b3152c6ed55c7039887d12a4c0 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Tue, 6 Jul 2021 16:59:14 -0700 Subject: [PATCH 03/21] Link tracking issue for pin_deref_mut --- library/core/src/pin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 85411bac946a4..6b1a12ed18c0f 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -810,7 +810,7 @@ impl<'a, P: DerefMut> Pin<&'a mut Pin

> { /// move in the future, and this method does not enable the pointee to move. "Malicious" /// implementations of `P::DerefMut` are likewise ruled out by the contract of /// `Pin::new_unchecked`. - #[unstable(feature = "pin_deref_mut", issue = "none")] + #[unstable(feature = "pin_deref_mut", issue = "86918")] #[inline(always)] pub fn as_deref_mut(self) -> Pin<&'a mut P::Target> { // SAFETY: What we're asserting here is that going from From 88aecc6b7f9339e1043d52422adcc96725919d27 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 1 Jun 2021 16:30:13 +0100 Subject: [PATCH 04/21] BufWriter: actually export WriterPanicked error I didn't notice the submodule, which means I failed to re-export this to make it actually-public. Reported-by: Andrew Gallant Signed-off-by: Ian Jackson --- library/std/src/io/buffered/mod.rs | 2 ++ library/std/src/io/mod.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/library/std/src/io/buffered/mod.rs b/library/std/src/io/buffered/mod.rs index 65497817f8160..d5996d102ec5b 100644 --- a/library/std/src/io/buffered/mod.rs +++ b/library/std/src/io/buffered/mod.rs @@ -14,6 +14,8 @@ use crate::io::Error; pub use bufreader::BufReader; pub use bufwriter::BufWriter; +#[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] +pub use bufwriter::WriterPanicked; pub use linewriter::LineWriter; use linewritershim::LineWriterShim; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index cc615b95f8625..dec8251ee0158 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -264,6 +264,8 @@ use crate::sys_common::memchr; #[stable(feature = "rust1", since = "1.0.0")] pub use self::buffered::IntoInnerError; +#[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] +pub use self::buffered::WriterPanicked; #[stable(feature = "rust1", since = "1.0.0")] pub use self::buffered::{BufReader, BufWriter, LineWriter}; #[stable(feature = "rust1", since = "1.0.0")] From 3aaa2756d10a9ac4dd9466487bd665c3dea37d5f Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 1 Jun 2021 16:47:26 +0100 Subject: [PATCH 05/21] BufWriter: rename `into_parts` from `into_raw_parts` I looked in stdlib and as @BurntSushi thought, `raw` is generally used for raw pointers, or other hazardous kinds of thing. stdlib does not have `into_parts` apart from the one I added to `IntoInnerError`. I did an ad-hoc search of the rustdocs for my current game project Otter, which includes quite a large number of dependencies. `into_parts` seems heavily used for things quite like this. So change this name. Suggested-by: Andrew Gallant Signed-off-by: Ian Jackson --- library/std/src/io/buffered/bufwriter.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs index ef2769d431fbb..884b6288463a6 100644 --- a/library/std/src/io/buffered/bufwriter.rs +++ b/library/std/src/io/buffered/bufwriter.rs @@ -319,7 +319,7 @@ impl BufWriter { /// In this case, we return `WriterPanicked` for the buffered data (from which the buffer /// contents can still be recovered). /// - /// `into_raw_parts` makes no attempt to flush data and cannot fail. + /// `into_parts` makes no attempt to flush data and cannot fail. /// /// # Examples /// @@ -331,12 +331,12 @@ impl BufWriter { /// let mut stream = BufWriter::new(buffer.as_mut()); /// write!(stream, "too much data").unwrap(); /// stream.flush().expect_err("it doesn't fit"); - /// let (recovered_writer, buffered_data) = stream.into_raw_parts(); + /// let (recovered_writer, buffered_data) = stream.into_parts(); /// assert_eq!(recovered_writer.len(), 0); /// assert_eq!(&buffered_data.unwrap(), b"ata"); /// ``` #[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] - pub fn into_raw_parts(mut self) -> (W, Result, WriterPanicked>) { + pub fn into_parts(mut self) -> (W, Result, WriterPanicked>) { let buf = mem::take(&mut self.buf); let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) }; (self.inner.take().unwrap(), buf) @@ -441,7 +441,7 @@ impl BufWriter { } #[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] -/// Error returned for the buffered data from `BufWriter::into_raw_parts`, when the underlying +/// Error returned for the buffered data from `BufWriter::into_parts`, when the underlying /// writer has previously panicked. Contains the (possibly partly written) buffered data. /// /// # Example @@ -463,7 +463,7 @@ impl BufWriter { /// stream.flush().unwrap() /// })); /// assert!(result.is_err()); -/// let (recovered_writer, buffered_data) = stream.into_raw_parts(); +/// let (recovered_writer, buffered_data) = stream.into_parts(); /// assert!(matches!(recovered_writer, PanickingWriter)); /// assert_eq!(buffered_data.unwrap_err().into_inner(), b"some data"); /// ``` From 51d16ac7a840aecda2083585cf1003e3012a7576 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 19 Jul 2021 17:33:55 +0100 Subject: [PATCH 06/21] Rename feature gate bufwriter_into_parts from bufwriter_into_raw_parts As requested https://github.com/rust-lang/rust/pull/85901#pullrequestreview-698404772 Signed-off-by: Ian Jackson --- library/std/src/io/buffered/bufwriter.rs | 16 ++++++++-------- library/std/src/io/buffered/mod.rs | 2 +- library/std/src/io/mod.rs | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs index 884b6288463a6..0515d1a4e992a 100644 --- a/library/std/src/io/buffered/bufwriter.rs +++ b/library/std/src/io/buffered/bufwriter.rs @@ -324,7 +324,7 @@ impl BufWriter { /// # Examples /// /// ``` - /// #![feature(bufwriter_into_raw_parts)] + /// #![feature(bufwriter_into_parts)] /// use std::io::{BufWriter, Write}; /// /// let mut buffer = [0u8; 10]; @@ -335,7 +335,7 @@ impl BufWriter { /// assert_eq!(recovered_writer.len(), 0); /// assert_eq!(&buffered_data.unwrap(), b"ata"); /// ``` - #[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] + #[unstable(feature = "bufwriter_into_parts", issue = "80690")] pub fn into_parts(mut self) -> (W, Result, WriterPanicked>) { let buf = mem::take(&mut self.buf); let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) }; @@ -440,14 +440,14 @@ impl BufWriter { } } -#[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] +#[unstable(feature = "bufwriter_into_parts", issue = "80690")] /// Error returned for the buffered data from `BufWriter::into_parts`, when the underlying /// writer has previously panicked. Contains the (possibly partly written) buffered data. /// /// # Example /// /// ``` -/// #![feature(bufwriter_into_raw_parts)] +/// #![feature(bufwriter_into_parts)] /// use std::io::{self, BufWriter, Write}; /// use std::panic::{catch_unwind, AssertUnwindSafe}; /// @@ -474,7 +474,7 @@ pub struct WriterPanicked { impl WriterPanicked { /// Returns the perhaps-unwritten data. Some of this data may have been written by the /// panicking call(s) to the underlying writer, so simply writing it again is not a good idea. - #[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] + #[unstable(feature = "bufwriter_into_parts", issue = "80690")] pub fn into_inner(self) -> Vec { self.buf } @@ -483,7 +483,7 @@ impl WriterPanicked { "BufWriter inner writer panicked, what data remains unwritten is not known"; } -#[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] +#[unstable(feature = "bufwriter_into_parts", issue = "80690")] impl error::Error for WriterPanicked { #[allow(deprecated, deprecated_in_future)] fn description(&self) -> &str { @@ -491,14 +491,14 @@ impl error::Error for WriterPanicked { } } -#[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] +#[unstable(feature = "bufwriter_into_parts", issue = "80690")] impl fmt::Display for WriterPanicked { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", Self::DESCRIPTION) } } -#[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] +#[unstable(feature = "bufwriter_into_parts", issue = "80690")] impl fmt::Debug for WriterPanicked { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("WriterPanicked") diff --git a/library/std/src/io/buffered/mod.rs b/library/std/src/io/buffered/mod.rs index d5996d102ec5b..6702aefd2e9f0 100644 --- a/library/std/src/io/buffered/mod.rs +++ b/library/std/src/io/buffered/mod.rs @@ -14,7 +14,7 @@ use crate::io::Error; pub use bufreader::BufReader; pub use bufwriter::BufWriter; -#[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] +#[unstable(feature = "bufwriter_into_parts", issue = "80690")] pub use bufwriter::WriterPanicked; pub use linewriter::LineWriter; use linewritershim::LineWriterShim; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index dec8251ee0158..c58abf2a737a3 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -264,7 +264,7 @@ use crate::sys_common::memchr; #[stable(feature = "rust1", since = "1.0.0")] pub use self::buffered::IntoInnerError; -#[unstable(feature = "bufwriter_into_raw_parts", issue = "80690")] +#[unstable(feature = "bufwriter_into_parts", issue = "80690")] pub use self::buffered::WriterPanicked; #[stable(feature = "rust1", since = "1.0.0")] pub use self::buffered::{BufReader, BufWriter, LineWriter}; From 8c91805fd13a8fd8c1c1d7f8a7fe3d7c953c9ee1 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Fri, 15 Jan 2021 19:16:41 +0100 Subject: [PATCH 07/21] Stabilize core::task::ready! --- library/core/src/task/mod.rs | 2 +- library/core/src/task/ready.rs | 6 +----- library/std/src/lib.rs | 1 - 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs index 3d6f4f5971a62..709f48aaa3ecd 100644 --- a/library/core/src/task/mod.rs +++ b/library/core/src/task/mod.rs @@ -11,5 +11,5 @@ mod wake; pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker}; mod ready; -#[unstable(feature = "ready_macro", issue = "70922")] +#[stable(feature = "ready_macro", since = "1.55.0")] pub use ready::ready; diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs index cbf6990001589..3cae76255d161 100644 --- a/library/core/src/task/ready.rs +++ b/library/core/src/task/ready.rs @@ -8,8 +8,6 @@ /// # Examples /// /// ``` -/// #![feature(ready_macro)] -/// /// use std::task::{ready, Context, Poll}; /// use std::future::{self, Future}; /// use std::pin::Pin; @@ -29,8 +27,6 @@ /// The `ready!` call expands to: /// /// ``` -/// # #![feature(ready_macro)] -/// # /// # use std::task::{Context, Poll}; /// # use std::future::{self, Future}; /// # use std::pin::Pin; @@ -49,7 +45,7 @@ /// # Poll::Ready(()) /// # } /// ``` -#[unstable(feature = "ready_macro", issue = "70922")] +#[stable(feature = "ready_macro", since = "1.55.0")] #[rustc_macro_transparency = "semitransparent"] pub macro ready($e:expr) { match $e { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index cfbfe7cc19160..22afd0bbc8cc9 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -304,7 +304,6 @@ #![feature(pin_static_ref)] #![feature(prelude_import)] #![feature(ptr_internals)] -#![feature(ready_macro)] #![feature(rustc_attrs)] #![feature(rustc_private)] #![feature(shrink_to)] From ec76b6eedddfd601a9684db945ff927e57f2aa03 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Jul 2021 14:48:57 +0200 Subject: [PATCH 08/21] Add support for tuple structs' fields documentation --- src/librustdoc/html/render/mod.rs | 3 +++ src/librustdoc/html/render/print_item.rs | 18 +++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 68c59612ccc44..5298a560627cb 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2007,6 +2007,9 @@ fn sidebar_struct(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, s: &clea } sidebar.push_str(""); + } else if let CtorKind::Fn = s.struct_type { + sidebar + .push_str("

Tuple Fields

"); } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 2dfbaff1cc995..8f7e84428956a 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1176,21 +1176,21 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St _ => None, }) .peekable(); - if let CtorKind::Fictive = s.struct_type { + if let CtorKind::Fictive | CtorKind::Fn = s.struct_type { if fields.peek().is_some() { write!( w, "

\ - Fields{}

", + {}{}\ + ", + if let CtorKind::Fictive = s.struct_type { "Fields" } else { "Tuple Fields" }, document_non_exhaustive_header(it) ); document_non_exhaustive(w, it); - for (field, ty) in fields { - let id = cx.derive_id(format!( - "{}.{}", - ItemType::StructField, - field.name.as_ref().unwrap() - )); + for (index, (field, ty)) in fields.enumerate() { + let field_name = + field.name.map_or_else(|| index.to_string(), |sym| (*sym.as_str()).to_string()); + let id = cx.derive_id(format!("{}.{}", ItemType::StructField, field_name)); write!( w, "\ @@ -1199,7 +1199,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St ", item_type = ItemType::StructField, id = id, - name = field.name.as_ref().unwrap(), + name = field_name, ty = ty.print(cx) ); document(w, cx, field, Some(it)); From 19f30b72b30c7745d3ed126ebeaf3fe3d253677f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Jul 2021 14:57:45 +0200 Subject: [PATCH 09/21] Add test for tuple struct documentation fields --- src/test/rustdoc/tuple-struct-fields-doc.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/test/rustdoc/tuple-struct-fields-doc.rs diff --git a/src/test/rustdoc/tuple-struct-fields-doc.rs b/src/test/rustdoc/tuple-struct-fields-doc.rs new file mode 100644 index 0000000000000..ab3d4903b2b6e --- /dev/null +++ b/src/test/rustdoc/tuple-struct-fields-doc.rs @@ -0,0 +1,19 @@ +#![crate_name = "foo"] + +// @has foo/struct.Foo.html +// @has - '//h2[@id="fields"]' 'Tuple Fields' +// @has - '//h3[@class="sidebar-title"]/a[@href="#fields"]' 'Tuple Fields' +// @has - '//*[@id="structfield.0"]' '0: u32' +// @has - '//*[@id="main"]/div[@class="docblock"]' 'hello' +// @!has - '//*[@id="structfield.1"]' +// @has - '//*[@id="structfield.2"]' '2: char' +// @has - '//*[@id="structfield.3"]' '3: i8' +// @has - '//*[@id="main"]/div[@class="docblock"]' 'not hello' +pub struct Foo( + /// hello + pub u32, + char, + pub char, + /// not hello + pub i8, +); From 2b790944a010498dd25a3bb327f2560927442c69 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Jul 2021 21:18:02 +0200 Subject: [PATCH 10/21] Add support for tuple struct fields documentation in enums as well --- src/librustdoc/clean/mod.rs | 4 +--- src/librustdoc/html/render/print_item.rs | 10 +++++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1a2852dc6c724..a5ad8dfeb6b96 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1730,9 +1730,7 @@ impl Clean for hir::VariantData<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Variant { match self { hir::VariantData::Struct(..) => Variant::Struct(self.clean(cx)), - hir::VariantData::Tuple(..) => { - Variant::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect()) - } + hir::VariantData::Tuple(..) => Variant::Struct(self.clean(cx)), hir::VariantData::Unit(..) => Variant::CLike, } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 8f7e84428956a..ea1cc8eb2ad52 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1037,8 +1037,9 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum write!(w, "
", id = variant_id); write!( w, - "

Fields of {name}

", - name = variant.name.as_ref().unwrap() + "

{extra}Fields of {name}

", + extra = if s.struct_type == CtorKind::Fn { "Tuple " } else { "" }, + name = variant.name.as_ref().unwrap(), ); for field in &s.fields { use crate::clean::StructFieldItem; @@ -1509,7 +1510,10 @@ fn render_struct( if let Some(g) = g { write!(w, "{}", print_where_clause(g, cx, 0, false),) } - w.write_str(";"); + // We only want a ";" when we are displaying a tuple struct, not a variant tuple struct. + if structhead { + w.write_str(";"); + } } CtorKind::Const => { // Needed for PhantomData. From fbf78e1f9cc80ba5a68078c3cf2cb4d03aa7b00c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Jul 2021 21:18:11 +0200 Subject: [PATCH 11/21] Add test for enum item tuple fields documentation --- src/test/rustdoc-ui/coverage/enums.stdout | 4 ++-- src/test/rustdoc/toggle-item-contents.rs | 4 ++-- src/test/rustdoc/tuple-struct-fields-doc.rs | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/test/rustdoc-ui/coverage/enums.stdout b/src/test/rustdoc-ui/coverage/enums.stdout index 64c012c1f66e3..414d60c86d308 100644 --- a/src/test/rustdoc-ui/coverage/enums.stdout +++ b/src/test/rustdoc-ui/coverage/enums.stdout @@ -1,7 +1,7 @@ +-------------------------------------+------------+------------+------------+------------+ | File | Documented | Percentage | Examples | Percentage | +-------------------------------------+------------+------------+------------+------------+ -| ...est/rustdoc-ui/coverage/enums.rs | 6 | 75.0% | 0 | 0.0% | +| ...est/rustdoc-ui/coverage/enums.rs | 6 | 66.7% | 0 | 0.0% | +-------------------------------------+------------+------------+------------+------------+ -| Total | 6 | 75.0% | 0 | 0.0% | +| Total | 6 | 66.7% | 0 | 0.0% | +-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc/toggle-item-contents.rs b/src/test/rustdoc/toggle-item-contents.rs index 8d2046591d08a..ae871e79d7f6b 100644 --- a/src/test/rustdoc/toggle-item-contents.rs +++ b/src/test/rustdoc/toggle-item-contents.rs @@ -81,8 +81,8 @@ pub enum EnumStructVariant { } // @has 'toggle_item_contents/enum.LargeEnum.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 variants' +// @count - '//*[@class="rust enum"]//details[@class="rustdoc-toggle type-contents-toggle"]' 1 +// @has - '//*[@class="rust enum"]//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 variants' pub enum LargeEnum { A, B, C, D, E, F(u8), G, H, I, J, K, L, M } diff --git a/src/test/rustdoc/tuple-struct-fields-doc.rs b/src/test/rustdoc/tuple-struct-fields-doc.rs index ab3d4903b2b6e..f3d8e39ea2d26 100644 --- a/src/test/rustdoc/tuple-struct-fields-doc.rs +++ b/src/test/rustdoc/tuple-struct-fields-doc.rs @@ -17,3 +17,20 @@ pub struct Foo( /// not hello pub i8, ); + +// @has foo/enum.Bar.html +// @has - '//pre[@class="rust enum"]' 'BarVariant(String),' +// @matches - '//*[@id="variant.BarVariant.fields"]/h3' '^Tuple Fields of BarVariant$' +// @has - '//*[@id="variant.BarVariant.field.0"]' '0: String' +// @has - '//*[@id="variant.BarVariant.fields"]//*[@class="docblock"]' 'Hello docs' +// @matches - '//*[@id="variant.FooVariant.fields"]/h3' '^Fields of FooVariant$' +pub enum Bar { + BarVariant( + /// Hello docs + String + ), + FooVariant { + /// hello + x: u32, + }, +} From beb9bb369a6a45149f41aac9fea3b5d7daa77c82 Mon Sep 17 00:00:00 2001 From: James Munns Date: Mon, 26 Jul 2021 21:09:04 +0200 Subject: [PATCH 12/21] Integrate context into the memorial to Anna --- src/test/ui/bastion-of-the-turbofish.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/test/ui/bastion-of-the-turbofish.rs b/src/test/ui/bastion-of-the-turbofish.rs index 233ddbbe11784..e12857008a5e0 100644 --- a/src/test/ui/bastion-of-the-turbofish.rs +++ b/src/test/ui/bastion-of-the-turbofish.rs @@ -20,13 +20,17 @@ // in permitting generic arguments to be provided without the consent of the // Great Turbofish. Should you be so naïve as to try to revolt against its // mighty clutches, here shall its wrath be indomitably displayed. This -// program must pass for all eternity, fundamentally at odds with an impetuous -// rebellion against the Turbofish. +// program must pass for all eternity: forever watched by the guardian angel +// which gave this beast its name, and stands fundamentally at odds with the +// impetuous rebellion against the Turbofish. // // My heart aches in sorrow, for I know I am defeated. Let this be a warning -// to all those who come after. Here stands the bastion of the Turbofish. +// to all those who come after: for they too must overcome the impassible +// hurdle of defeating the great beast, championed by a resolute winged +// guardian. // -// RIP Anna Harren, Guardian Angel of the Hallowed Turbofish. <3 +// Here stands the Bastion of the Turbofish, a memorial to Anna Harren, +// Guardian Angel of these Hallowed Grounds. <3 // See https://github.com/rust-lang/rust/pull/53562 // and https://github.com/rust-lang/rfcs/pull/2527 @@ -34,6 +38,6 @@ // for context. fn main() { - let (oh, woe, is, me) = ("the", "Turbofish", "remains", "undefeated"); - let _: (bool, bool) = (oh(me)); + let (the, guardian, stands, resolute) = ("the", "Turbofish", "remains", "undefeated"); + let _: (bool, bool) = (the(resolute)); } From c4aa73525bbfef6895612599170a5b297e1625ba Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 27 Jul 2021 13:52:15 +0200 Subject: [PATCH 13/21] Add explanations for why we use Variant::Struct instead of Variant::Tuple for tuple structs in enums --- src/librustdoc/clean/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a5ad8dfeb6b96..cf837024a8ed3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1730,6 +1730,12 @@ impl Clean for hir::VariantData<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Variant { match self { hir::VariantData::Struct(..) => Variant::Struct(self.clean(cx)), + // Important note here: `Variant::Tuple` is used on tuple structs which are not in an + // enum (so where converting from `ty::VariantDef`). In case we are in an enum, the kind + // is provided by the `Variant` wrapper directly, and since we need the fields' name + // (even for a tuple struct variant!), it's simpler to just store it as a + // `Variant::Struct` instead of a `Variant::Tuple` (otherwise it would force us to make + // a lot of changes when rendering them to generate the name as well). hir::VariantData::Tuple(..) => Variant::Struct(self.clean(cx)), hir::VariantData::Unit(..) => Variant::CLike, } From 7f563f7f4e279c9a556537f0b99e9eec076782ae Mon Sep 17 00:00:00 2001 From: Chris Midgley Date: Tue, 27 Jul 2021 18:06:34 +0100 Subject: [PATCH 14/21] Add long explanation for E0498 --- compiler/rustc_error_codes/src/error_codes.rs | 2 +- .../src/error_codes/E0498.md | 22 +++++++++++++++++++ src/test/ui-fulldeps/plugin-args.stderr | 1 + .../ui/malformed/malformed-plugin-3.stderr | 1 + 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0498.md diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 6f65d386f0d1b..65999ba707c85 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -248,6 +248,7 @@ E0493: include_str!("./error_codes/E0493.md"), E0495: include_str!("./error_codes/E0495.md"), E0496: include_str!("./error_codes/E0496.md"), E0497: include_str!("./error_codes/E0497.md"), +E0498: include_str!("./error_codes/E0498.md"), E0499: include_str!("./error_codes/E0499.md"), E0500: include_str!("./error_codes/E0500.md"), E0501: include_str!("./error_codes/E0501.md"), @@ -604,7 +605,6 @@ E0783: include_str!("./error_codes/E0783.md"), // E0488, // lifetime of variable does not enclose its declaration // E0489, // type/lifetime parameter not in scope here E0490, // a value of type `..` is borrowed for too long - E0498, // malformed plugin attribute E0514, // metadata version mismatch E0519, // local crate and dependency have same (crate-name, disambiguator) // two dependencies have same (crate-name, disambiguator) but different SVH diff --git a/compiler/rustc_error_codes/src/error_codes/E0498.md b/compiler/rustc_error_codes/src/error_codes/E0498.md new file mode 100644 index 0000000000000..822a1a9138a6b --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0498.md @@ -0,0 +1,22 @@ +The `plugin` attribute was malformed. + +Erroneous code example: + +```compile_fail,E0498 +#![feature(plugin)] +#![plugin(foo(args))] // error: invalid argument +#![plugin(bar="test")] // error: invalid argument +``` + +The `#[plugin]` attribute should take a single argument: the name of the plugin. + +For example, for the plugin `foo`: + +``` +#![feature(plugin)] +#![plugin(foo)] // ok! +``` + +See the [`plugin` feature] section of the Unstable book for more details. + +[`plugin` feature]: https://doc.rust-lang.org/nightly/unstable-book/language-features/plugin.html diff --git a/src/test/ui-fulldeps/plugin-args.stderr b/src/test/ui-fulldeps/plugin-args.stderr index 2e255f185e291..177f33005c8cb 100644 --- a/src/test/ui-fulldeps/plugin-args.stderr +++ b/src/test/ui-fulldeps/plugin-args.stderr @@ -14,3 +14,4 @@ LL | #![plugin(empty_plugin(args))] error: aborting due to previous error; 1 warning emitted +For more information about this error, try `rustc --explain E0498`. diff --git a/src/test/ui/malformed/malformed-plugin-3.stderr b/src/test/ui/malformed/malformed-plugin-3.stderr index 11abdb16e0b4e..64cb429ea745b 100644 --- a/src/test/ui/malformed/malformed-plugin-3.stderr +++ b/src/test/ui/malformed/malformed-plugin-3.stderr @@ -14,3 +14,4 @@ LL | #![plugin(foo="bleh")] error: aborting due to previous error; 1 warning emitted +For more information about this error, try `rustc --explain E0498`. From bc70252f5039281388028faf2adec9c6f58aeab3 Mon Sep 17 00:00:00 2001 From: Chris Midgley Date: Tue, 27 Jul 2021 19:44:50 +0100 Subject: [PATCH 15/21] Mark code as ignored due to requiring external plugin --- compiler/rustc_error_codes/src/error_codes/E0498.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0498.md b/compiler/rustc_error_codes/src/error_codes/E0498.md index 822a1a9138a6b..c9ea4a7947f6c 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0498.md +++ b/compiler/rustc_error_codes/src/error_codes/E0498.md @@ -12,7 +12,7 @@ The `#[plugin]` attribute should take a single argument: the name of the plugin. For example, for the plugin `foo`: -``` +```ignore (requires external plugin crate) #![feature(plugin)] #![plugin(foo)] // ok! ``` From 40b57be5478935764ddfc45501169dbf921e939f Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Tue, 27 Jul 2021 19:47:39 +0200 Subject: [PATCH 16/21] Don't run MIR unsafeck at all when using `-Zthir-unsafeck` --- compiler/rustc_mir/src/transform/mod.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 3fbc81d5426ee..e58a7d903082e 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -259,10 +259,12 @@ fn mir_const<'tcx>( } // Unsafety check uses the raw mir, so make sure it is run. - if let Some(param_did) = def.const_param_did { - tcx.ensure().unsafety_check_result_for_const_arg((def.did, param_did)); - } else { - tcx.ensure().unsafety_check_result(def.did); + if !tcx.sess.opts.debugging_opts.thir_unsafeck { + if let Some(param_did) = def.const_param_did { + tcx.ensure().unsafety_check_result_for_const_arg((def.did, param_did)); + } else { + tcx.ensure().unsafety_check_result(def.did); + } } let mut body = tcx.mir_built(def).steal(); From 4b5ac09e326907c26aa3988044dbc7ef420e39e2 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 28 Jul 2021 15:18:18 +0200 Subject: [PATCH 17/21] add CI_ONLY_WHEN_CHANNEL and run x86_64-gnu-stable only on nightly --- .github/workflows/ci.yml | 1 + src/ci/github-actions/ci.yml | 4 ++ src/ci/scripts/should-skip-this.sh | 62 ++++++++++++++++++------------ 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36362635b1545..fe67a14c0fe45 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -263,6 +263,7 @@ jobs: env: IMAGE: x86_64-gnu RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable + CI_ONLY_WHEN_CHANNEL: nightly os: ubuntu-latest-xl - name: x86_64-gnu-aux os: ubuntu-latest-xl diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index e704071e401b7..128897e580b68 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -416,6 +416,10 @@ jobs: env: IMAGE: x86_64-gnu RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable + # Only run this job on the nightly channel. Running this on beta + # could cause failures when `dev: 1` in `stage0.txt`, and running + # this on stable is useless. + CI_ONLY_WHEN_CHANNEL: nightly <<: *job-linux-xl - name: x86_64-gnu-aux diff --git a/src/ci/scripts/should-skip-this.sh b/src/ci/scripts/should-skip-this.sh index fa738fe70c8e2..bb48fcb5a216e 100755 --- a/src/ci/scripts/should-skip-this.sh +++ b/src/ci/scripts/should-skip-this.sh @@ -8,31 +8,43 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" -if [[ -z "${CI_ONLY_WHEN_SUBMODULES_CHANGED+x}" ]]; then - echo "Executing the job since there is no skip rule in effect" - exit 0 +if [[ -n "${CI_ONLY_WHEN_SUBMODULES_CHANGED-}" ]]; then + git fetch "https://github.com/$GITHUB_REPOSITORY" "$GITHUB_BASE_REF" + BASE_COMMIT="$(git merge-base FETCH_HEAD HEAD)" + + echo "Searching for toolstate changes between $BASE_COMMIT and $(git rev-parse HEAD)" + + if git diff "$BASE_COMMIT" | grep --quiet "^index .* 160000"; then + # Submodules pseudo-files inside git have the 160000 permissions, so when + # those files are present in the diff a submodule was updated. + echo "Submodules were updated" + elif ! git diff --quiet "$BASE_COMMIT" -- src/tools/clippy src/tools/rustfmt; then + # There is not an easy blanket search for subtrees. For now, manually list + # the subtrees. + echo "Clippy or rustfmt subtrees were updated" + elif ! (git diff --quiet "$BASE_COMMIT" -- \ + src/test/rustdoc-gui \ + src/librustdoc \ + src/tools/rustdoc-gui); then + # There was a change in either rustdoc or in its GUI tests. + echo "Rustdoc was updated" + else + echo "Not executing this job since no submodules nor subtrees were updated" + ciCommandSetEnv SKIP_JOB 1 + exit 0 + fi fi -git fetch "https://github.com/$GITHUB_REPOSITORY" "$GITHUB_BASE_REF" -BASE_COMMIT="$(git merge-base FETCH_HEAD HEAD)" - -echo "Searching for toolstate changes between $BASE_COMMIT and $(git rev-parse HEAD)" - -if git diff "$BASE_COMMIT" | grep --quiet "^index .* 160000"; then - # Submodules pseudo-files inside git have the 160000 permissions, so when - # those files are present in the diff a submodule was updated. - echo "Executing the job since submodules are updated" -elif ! git diff --quiet "$BASE_COMMIT" -- src/tools/clippy src/tools/rustfmt; then - # There is not an easy blanket search for subtrees. For now, manually list - # the subtrees. - echo "Executing the job since clippy or rustfmt subtree was updated" -elif ! (git diff --quiet "$BASE_COMMIT" -- \ - src/test/rustdoc-gui \ - src/librustdoc \ - src/tools/rustdoc-gui); then - # There was a change in either rustdoc or in its GUI tests. - echo "Executing the job since rustdoc was updated" -else - echo "Not executing this job since no submodules nor subtrees were updated" - ciCommandSetEnv SKIP_JOB 1 +if [[ -n "${CI_ONLY_WHEN_CHANNEL-}" ]]; then + if [[ "${CI_ONLY_WHEN_CHANNEL}" = "$(cat src/ci/channel)" ]]; then + echo "The channel is the expected one" + else + echo "Not executing this job as the channel is not the expected one" + ciCommandSetEnv SKIP_JOB 1 + exit 0 + fi fi + + +echo "Executing the job since there is no skip rule preventing the execution" +exit 0 From 18cc06c848ec2707c3593f8e2ea6e7090e17ff16 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 28 Jul 2021 16:54:53 +0200 Subject: [PATCH 18/21] Update stable version of ready!() macro. --- library/core/src/task/mod.rs | 2 +- library/core/src/task/ready.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs index 709f48aaa3ecd..5f077f77bbc9f 100644 --- a/library/core/src/task/mod.rs +++ b/library/core/src/task/mod.rs @@ -11,5 +11,5 @@ mod wake; pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker}; mod ready; -#[stable(feature = "ready_macro", since = "1.55.0")] +#[stable(feature = "ready_macro", since = "1.56.0")] pub use ready::ready; diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs index 3cae76255d161..2834ca5fe2224 100644 --- a/library/core/src/task/ready.rs +++ b/library/core/src/task/ready.rs @@ -45,7 +45,7 @@ /// # Poll::Ready(()) /// # } /// ``` -#[stable(feature = "ready_macro", since = "1.55.0")] +#[stable(feature = "ready_macro", since = "1.56.0")] #[rustc_macro_transparency = "semitransparent"] pub macro ready($e:expr) { match $e { From 387cd6dbf67754472b59ab4810a7e15107d86f2b Mon Sep 17 00:00:00 2001 From: D1mon <3872485+D1mon@users.noreply.github.com> Date: Sat, 3 Jul 2021 15:31:16 +0300 Subject: [PATCH 19/21] Add some doc aliases Add `mkdir` to `create_dir`, `rmdir` to `remove_dir`. --- library/std/src/fs.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index bbe1ab40537f2..f72f88bb05c9d 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1912,6 +1912,7 @@ pub fn canonicalize>(path: P) -> io::Result { /// Ok(()) /// } /// ``` +#[doc(alias = "mkdir")] #[stable(feature = "rust1", since = "1.0.0")] pub fn create_dir>(path: P) -> io::Result<()> { DirBuilder::new().create(path.as_ref()) @@ -1991,6 +1992,7 @@ pub fn create_dir_all>(path: P) -> io::Result<()> { /// Ok(()) /// } /// ``` +#[doc(alias = "rmdir")] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir>(path: P) -> io::Result<()> { fs_imp::rmdir(path.as_ref()) From 2d8b6e34765994a4b0d3bc68a0ed950a16083baa Mon Sep 17 00:00:00 2001 From: Ibraheem Ahmed Date: Wed, 28 Jul 2021 16:22:34 -0400 Subject: [PATCH 20/21] Use backticks when referring to `core::future::Ready` in panic message --- library/core/src/future/ready.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/future/ready.rs b/library/core/src/future/ready.rs index b0c7fbb1d7a76..cc905d288f9e0 100644 --- a/library/core/src/future/ready.rs +++ b/library/core/src/future/ready.rs @@ -20,7 +20,7 @@ impl Future for Ready { #[inline] fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - Poll::Ready(self.0.take().expect("Ready polled after completion")) + Poll::Ready(self.0.take().expect("`Ready` polled after completion")) } } From 00198dd902ba36420ac89d6251f589fb67ed6398 Mon Sep 17 00:00:00 2001 From: Ibraheem Ahmed Date: Sat, 24 Jul 2021 13:58:08 -0400 Subject: [PATCH 21/21] fix example code for E0617 --- compiler/rustc_error_codes/src/error_codes/E0617.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0617.md b/compiler/rustc_error_codes/src/error_codes/E0617.md index 1c5d1f87b912b..eed384b495946 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0617.md +++ b/compiler/rustc_error_codes/src/error_codes/E0617.md @@ -3,12 +3,13 @@ Attempted to pass an invalid type of variable into a variadic function. Erroneous code example: ```compile_fail,E0617 +# use std::os::raw::{c_char, c_int}; extern "C" { - fn printf(c: *const i8, ...); + fn printf(format: *const c_char, ...) -> c_int; } unsafe { - printf(::std::ptr::null(), 0f32); + printf("%f\n\0".as_ptr() as _, 0f32); // error: cannot pass an `f32` to variadic function, cast to `c_double` } ``` @@ -21,10 +22,12 @@ to import from `std::os::raw`). In this case, `c_double` has the same size as `f64` so we can use it directly: ```no_run +# use std::os::raw::{c_char, c_int}; # extern "C" { -# fn printf(c: *const i8, ...); +# fn printf(format: *const c_char, ...) -> c_int; # } + unsafe { - printf(::std::ptr::null(), 0f64); // ok! + printf("%f\n\0".as_ptr() as _, 0f64); // ok! } ```