From 7a477869b72e2e053182d677b3b8f785796ee95d Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Thu, 26 Aug 2021 15:59:40 +0300 Subject: [PATCH 01/12] Makes docs for references a little less confusing - Make clear that the `Pointer` trait is related to formatting - Make clear that `&T` (shared reference) implements `Send` (if `T: Send + Sync`) --- library/std/src/primitive_docs.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 0de9126dab2fe..ca7b2da9566ea 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -1104,11 +1104,11 @@ mod prim_usize {} /// * [`Clone`] \(Note that this will not defer to `T`'s `Clone` implementation if it exists!) /// * [`Deref`] /// * [`Borrow`] -/// * [`Pointer`] +/// * [`fmt::Pointer`] /// /// [`Deref`]: ops::Deref /// [`Borrow`]: borrow::Borrow -/// [`Pointer`]: fmt::Pointer +/// [`fmt::Pointer`]: fmt::Pointer /// /// `&mut T` references get all of the above except `Copy` and `Clone` (to prevent creating /// multiple simultaneous mutable borrows), plus the following, regardless of the type of its @@ -1124,7 +1124,7 @@ mod prim_usize {} /// The following traits are implemented on `&T` references if the underlying `T` also implements /// that trait: /// -/// * All the traits in [`std::fmt`] except [`Pointer`] and [`fmt::Write`] +/// * All the traits in [`std::fmt`] except [`fmt::Pointer`] (which is implemented regardless of the type of its referent) and [`fmt::Write`] /// * [`PartialOrd`] /// * [`Ord`] /// * [`PartialEq`] @@ -1133,9 +1133,10 @@ mod prim_usize {} /// * [`Fn`] \(in addition, `&T` references get [`FnMut`] and [`FnOnce`] if `T: Fn`) /// * [`Hash`] /// * [`ToSocketAddrs`] +/// * [`Send`] \(`&T` references also require T: [Sync]) /// /// [`std::fmt`]: fmt -/// ['Pointer`]: fmt::Pointer +/// ['fmt::Pointer`]: fmt::Pointer /// [`Hash`]: hash::Hash #[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))] /// @@ -1150,7 +1151,6 @@ mod prim_usize {} /// * [`ExactSizeIterator`] /// * [`FusedIterator`] /// * [`TrustedLen`] -/// * [`Send`] \(note that `&T` references only get `Send` if T: [Sync]) /// * [`io::Write`] /// * [`Read`] /// * [`Seek`] From 9a4530bdd00f5df42e750e2596fb2cc992fa3627 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Fri, 27 Aug 2021 00:16:25 +0300 Subject: [PATCH 02/12] Update library/std/src/primitive_docs.rs Co-authored-by: fmease --- library/std/src/primitive_docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index ca7b2da9566ea..d919f8ee31e38 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -1136,7 +1136,7 @@ mod prim_usize {} /// * [`Send`] \(`&T` references also require T: [Sync]) /// /// [`std::fmt`]: fmt -/// ['fmt::Pointer`]: fmt::Pointer +/// [`fmt::Pointer`]: fmt::Pointer /// [`Hash`]: hash::Hash #[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))] /// From 26aec6c9363345d14ca38d7630dc9478239fbd77 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sun, 10 Oct 2021 14:11:58 +0300 Subject: [PATCH 03/12] Update core primitives_docs.rs up to date with std --- library/core/src/primitive_docs.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 0de9126dab2fe..d919f8ee31e38 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1104,11 +1104,11 @@ mod prim_usize {} /// * [`Clone`] \(Note that this will not defer to `T`'s `Clone` implementation if it exists!) /// * [`Deref`] /// * [`Borrow`] -/// * [`Pointer`] +/// * [`fmt::Pointer`] /// /// [`Deref`]: ops::Deref /// [`Borrow`]: borrow::Borrow -/// [`Pointer`]: fmt::Pointer +/// [`fmt::Pointer`]: fmt::Pointer /// /// `&mut T` references get all of the above except `Copy` and `Clone` (to prevent creating /// multiple simultaneous mutable borrows), plus the following, regardless of the type of its @@ -1124,7 +1124,7 @@ mod prim_usize {} /// The following traits are implemented on `&T` references if the underlying `T` also implements /// that trait: /// -/// * All the traits in [`std::fmt`] except [`Pointer`] and [`fmt::Write`] +/// * All the traits in [`std::fmt`] except [`fmt::Pointer`] (which is implemented regardless of the type of its referent) and [`fmt::Write`] /// * [`PartialOrd`] /// * [`Ord`] /// * [`PartialEq`] @@ -1133,9 +1133,10 @@ mod prim_usize {} /// * [`Fn`] \(in addition, `&T` references get [`FnMut`] and [`FnOnce`] if `T: Fn`) /// * [`Hash`] /// * [`ToSocketAddrs`] +/// * [`Send`] \(`&T` references also require T: [Sync]) /// /// [`std::fmt`]: fmt -/// ['Pointer`]: fmt::Pointer +/// [`fmt::Pointer`]: fmt::Pointer /// [`Hash`]: hash::Hash #[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))] /// @@ -1150,7 +1151,6 @@ mod prim_usize {} /// * [`ExactSizeIterator`] /// * [`FusedIterator`] /// * [`TrustedLen`] -/// * [`Send`] \(note that `&T` references only get `Send` if T: [Sync]) /// * [`io::Write`] /// * [`Read`] /// * [`Seek`] From 69df43b041f76251391f11264c1ff763ca2a64a0 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Tue, 19 Oct 2021 22:48:53 -0700 Subject: [PATCH 04/12] Improve display of enum variants Use h3 and h4 for the variant name and the "Fields" subheading. Remove the "of T" part of the "Fields" subheading. Remove border-bottom from "Fields" subheading. Move docblock below "Fields" listing. --- src/librustdoc/html/render/print_item.rs | 24 ++++++------- src/librustdoc/html/static/css/rustdoc.css | 29 ++++++++------- src/test/rustdoc-gui/headings.goml | 40 ++++++++++----------- src/test/rustdoc/enum-headings.rs | 40 +++++++++++++++++++++ src/test/rustdoc/tuple-struct-fields-doc.rs | 4 +-- 5 files changed, 89 insertions(+), 48 deletions(-) create mode 100644 src/test/rustdoc/enum-headings.rs diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index d07ef6db4c6b0..096541423c6c1 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1080,7 +1080,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.as_ref().unwrap())); write!( w, - "
\ + "

\ \ {name}", id = id, @@ -1093,9 +1093,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum } w.write_str(""); render_stability_since(w, variant, it, cx.tcx()); - w.write_str("

"); - document(w, cx, variant, Some(it), HeadingOffset::H3); - document_non_exhaustive(w, variant); + w.write_str(""); use crate::clean::Variant; if let Some((extra, fields)) = match *variant.kind { @@ -1109,12 +1107,8 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum variant.name.as_ref().unwrap() )); write!(w, "
", id = variant_id); - write!( - w, - "

{extra}Fields of {name}

", - extra = extra, - name = variant.name.as_ref().unwrap(), - ); + write!(w, "

{extra}Fields

", extra = extra,); + document_non_exhaustive(w, variant); for field in fields { match *field.kind { clean::StrippedItem(box clean::StructFieldItem(_)) => {} @@ -1126,7 +1120,8 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum )); write!( w, - "\ + "
\ + \ \ {f}: {t}\ ", @@ -1134,13 +1129,16 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum f = field.name.as_ref().unwrap(), t = ty.print(cx) ); - document(w, cx, field, Some(variant), HeadingOffset::H4); + document(w, cx, field, Some(variant), HeadingOffset::H5); + write!(w, "
"); } _ => unreachable!(), } } - w.write_str("
"); + w.write_str(""); } + + document(w, cx, variant, Some(it), HeadingOffset::H4); } } let def_id = it.def_id.expect_def_id(); diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 93cbc0debb945..968e40ec4cb0b 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1101,25 +1101,28 @@ a.test-arrow:hover{ margin-right: 5px; } -.sub-variant, .sub-variant > h3 { - margin-top: 0px !important; - padding-top: 1px; +h3.variant { + font-weight: 600; + font-size: 1.1em; + margin-bottom: 10px; + border-bottom: none; } -#main .sub-variant > h3 { - font-size: 15px; - margin-left: 25px; - margin-bottom: 5px; +.sub-variant h4 { + font-size: 1em; + font-weight: 400; + border-bottom: none; + margin-top: 0; + margin-bottom: 0; } -.sub-variant > div { - margin-left: 20px; - margin-bottom: 10px; +.sub-variant { + margin-left: 24px; + margin-bottom: 40px; } -.sub-variant > div > span { - display: block; - position: relative; +.sub-variant > .sub-variant-field { + margin-left: 24px; } .toggle-label { diff --git a/src/test/rustdoc-gui/headings.goml b/src/test/rustdoc-gui/headings.goml index 35d772170f6f9..3b5cfeb68af61 100644 --- a/src/test/rustdoc-gui/headings.goml +++ b/src/test/rustdoc-gui/headings.goml @@ -1,4 +1,4 @@ -// This test check that headers (a) have the correct heading level, (b) are the right size, +// This test checks that headers (a) have the correct heading level, (b) are the right size, // and (c) have the correct underlining (or absence of underlining). // The sizes may change as design changes, but try to make sure a lower header is never bigger than // its parent headers. Also make sure lower headers don't have underlines when their parents lack @@ -67,25 +67,25 @@ assert-css: ("h4#top-doc-prose-sub-sub-heading", {"border-bottom-width": "1px"}) assert-css: ("h2#variants", {"font-size": "22.4px"}) assert-css: ("h2#variants", {"border-bottom-width": "1px"}) -assert-css: ("h3#none-prose-title", {"font-size": "20.8px"}) -assert-css: ("h3#none-prose-title", {"border-bottom-width": "0px"}) -assert-css: ("h4#none-prose-sub-heading", {"font-size": "16px"}) -assert-css: ("h4#none-prose-sub-heading", {"border-bottom-width": "0px"}) - -assert-css: ("h3#wrapped-prose-title", {"font-size": "20.8px"}) -assert-css: ("h3#wrapped-prose-title", {"border-bottom-width": "0px"}) -assert-css: ("h4#wrapped-prose-sub-heading", {"font-size": "16px"}) -assert-css: ("h4#wrapped-prose-sub-heading", {"border-bottom-width": "0px"}) - -assert-css: ("h4#wrapped0-prose-title", {"font-size": "16px"}) -assert-css: ("h4#wrapped0-prose-title", {"border-bottom-width": "0px"}) -assert-css: ("h5#wrapped0-prose-sub-heading", {"font-size": "16px"}) -assert-css: ("h5#wrapped0-prose-sub-heading", {"border-bottom-width": "0px"}) - -assert-css: ("h4#structy-prose-title", {"font-size": "16px"}) -assert-css: ("h4#structy-prose-title", {"border-bottom-width": "0px"}) -assert-css: ("h5#structy-prose-sub-heading", {"font-size": "16px"}) -assert-css: ("h5#structy-prose-sub-heading", {"border-bottom-width": "0px"}) +assert-css: ("h4#none-prose-title", {"font-size": "16px"}) +assert-css: ("h4#none-prose-title", {"border-bottom-width": "0px"}) +assert-css: ("h5#none-prose-sub-heading", {"font-size": "16px"}) +assert-css: ("h5#none-prose-sub-heading", {"border-bottom-width": "0px"}) + +assert-css: ("h4#wrapped-prose-title", {"font-size": "16px"}) +assert-css: ("h4#wrapped-prose-title", {"border-bottom-width": "0px"}) +assert-css: ("h5#wrapped-prose-sub-heading", {"font-size": "16px"}) +assert-css: ("h5#wrapped-prose-sub-heading", {"border-bottom-width": "0px"}) + +assert-css: ("h5#wrapped0-prose-title", {"font-size": "16px"}) +assert-css: ("h5#wrapped0-prose-title", {"border-bottom-width": "0px"}) +assert-css: ("h6#wrapped0-prose-sub-heading", {"font-size": "15.2px"}) +assert-css: ("h6#wrapped0-prose-sub-heading", {"border-bottom-width": "0px"}) + +assert-css: ("h5#structy-prose-title", {"font-size": "16px"}) +assert-css: ("h5#structy-prose-title", {"border-bottom-width": "0px"}) +assert-css: ("h6#structy-prose-sub-heading", {"font-size": "15.2px"}) +assert-css: ("h6#structy-prose-sub-heading", {"border-bottom-width": "0px"}) assert-css: ("h2#implementations", {"font-size": "22.4px"}) assert-css: ("h2#implementations", {"border-bottom-width": "1px"}) diff --git a/src/test/rustdoc/enum-headings.rs b/src/test/rustdoc/enum-headings.rs new file mode 100644 index 0000000000000..2e5c34391c4af --- /dev/null +++ b/src/test/rustdoc/enum-headings.rs @@ -0,0 +1,40 @@ +#![crate_name = "foo"] +// @has foo/enum.Token.html +/// A token! +/// # First +/// Some following text... +// @has - '//h2[@id="first"]' "First" +pub enum Token { + /// A declaration! + /// # Variant-First + /// Some following text... + // @has - '//h4[@id="variant-first"]' "Variant-First" + Declaration { + /// A version! + /// # Variant-Field-First + /// Some following text... + // @has - '//h5[@id="variant-field-first"]' "Variant-Field-First" + version: String, + }, + /// A Zoople! + /// # Variant-First + Zoople( + // @has - '//h5[@id="variant-tuple-field-first"]' "Variant-Tuple-Field-First" + /// Zoople's first variant! + /// # Variant-Tuple-Field-First + /// Some following text... + usize, + ), + /// Unfinished business! + /// # Non-Exhaustive-First + /// Some following text... + // @has - '//h4[@id="non-exhaustive-first"]' "Non-Exhaustive-First" + #[non_exhaustive] + Unfinished { + /// This is x. + /// # X-First + /// Some following text... + // @has - '//h5[@id="x-first"]' "X-First" + x: usize, + }, +} diff --git a/src/test/rustdoc/tuple-struct-fields-doc.rs b/src/test/rustdoc/tuple-struct-fields-doc.rs index f3d8e39ea2d26..139c5b4391ab7 100644 --- a/src/test/rustdoc/tuple-struct-fields-doc.rs +++ b/src/test/rustdoc/tuple-struct-fields-doc.rs @@ -20,10 +20,10 @@ pub struct Foo( // @has foo/enum.Bar.html // @has - '//pre[@class="rust enum"]' 'BarVariant(String),' -// @matches - '//*[@id="variant.BarVariant.fields"]/h3' '^Tuple Fields of BarVariant$' +// @matches - '//*[@id="variant.BarVariant.fields"]/h4' '^Tuple Fields$' // @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$' +// @matches - '//*[@id="variant.FooVariant.fields"]/h4' '^Fields$' pub enum Bar { BarVariant( /// Hello docs From 8f6fa4f548a57d11b93e8c9a1f20628783d6e4d7 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 17 Nov 2021 03:52:38 +0900 Subject: [PATCH 05/12] Add a regression test for #87573 --- src/test/ui/lang-items/issue-87573.rs | 28 +++++++++++++++++++++++ src/test/ui/lang-items/issue-87573.stderr | 21 +++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/test/ui/lang-items/issue-87573.rs create mode 100644 src/test/ui/lang-items/issue-87573.stderr diff --git a/src/test/ui/lang-items/issue-87573.rs b/src/test/ui/lang-items/issue-87573.rs new file mode 100644 index 0000000000000..aeb0c245a72ec --- /dev/null +++ b/src/test/ui/lang-items/issue-87573.rs @@ -0,0 +1,28 @@ +// Regression test for #87573, ensures that duplicate lang items or invalid generics +// for lang items doesn't cause ICE. + +#![feature(no_core, lang_items)] +#![no_core] +#![crate_type = "lib"] + +pub static STATIC_BOOL: bool = true; + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[lang = "sync"] +trait Sync {} +impl Sync for bool {} + +#[lang = "drop_in_place"] +//~^ ERROR: `drop_in_place` language item must be applied to a function with at least 1 generic argument +fn drop_fn() { + while false {} +} + +#[lang = "start"] +//~^ ERROR: `start` language item must be applied to a function with 1 generic argument +fn start(){} diff --git a/src/test/ui/lang-items/issue-87573.stderr b/src/test/ui/lang-items/issue-87573.stderr new file mode 100644 index 0000000000000..25560cfa0e6c7 --- /dev/null +++ b/src/test/ui/lang-items/issue-87573.stderr @@ -0,0 +1,21 @@ +error[E0718]: `drop_in_place` language item must be applied to a function with at least 1 generic argument + --> $DIR/issue-87573.rs:20:1 + | +LL | #[lang = "drop_in_place"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn drop_fn() { + | - this function has 0 generic arguments + +error[E0718]: `start` language item must be applied to a function with 1 generic argument + --> $DIR/issue-87573.rs:26:1 + | +LL | #[lang = "start"] + | ^^^^^^^^^^^^^^^^^ +LL | +LL | fn start(){} + | - this function has 0 generic arguments + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0718`. From 2f1a1f530b253b98e41a138b159c19481eb42269 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 17 Nov 2021 22:29:21 -0500 Subject: [PATCH 06/12] fix CTFE/Miri simd_insert/extract on array-style repr(simd) types --- .../src/interpret/intrinsics.rs | 47 +++++++------------ .../rustc_const_eval/src/interpret/operand.rs | 12 +++++ .../rustc_const_eval/src/interpret/place.rs | 28 ++++++++++- compiler/rustc_middle/src/ty/sty.rs | 5 ++ .../consts/const-eval/simd/insert_extract.rs | 13 ++--- 5 files changed, 67 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 698742fe98ceb..44da27a43db0a 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -413,48 +413,33 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::simd_insert => { let index = u64::from(self.read_scalar(&args[1])?.to_u32()?); let elem = &args[2]; - let input = &args[0]; - let (len, e_ty) = input.layout.ty.simd_size_and_type(*self.tcx); + let (input, input_len) = self.operand_to_simd(&args[0])?; + let (dest, dest_len) = self.place_to_simd(dest)?; + assert_eq!(input_len, dest_len, "Return vector length must match input length"); assert!( - index < len, - "Index `{}` must be in bounds of vector type `{}`: `[0, {})`", + index < dest_len, + "Index `{}` must be in bounds of vector with length {}`", index, - e_ty, - len - ); - assert_eq!( - input.layout, dest.layout, - "Return type `{}` must match vector type `{}`", - dest.layout.ty, input.layout.ty - ); - assert_eq!( - elem.layout.ty, e_ty, - "Scalar element type `{}` must match vector element type `{}`", - elem.layout.ty, e_ty + dest_len ); - for i in 0..len { - let place = self.place_index(dest, i)?; - let value = if i == index { *elem } else { self.operand_index(input, i)? }; - self.copy_op(&value, &place)?; + for i in 0..dest_len { + let place = self.mplace_index(&dest, i)?; + let value = + if i == index { *elem } else { self.mplace_index(&input, i)?.into() }; + self.copy_op(&value, &place.into())?; } } sym::simd_extract => { let index = u64::from(self.read_scalar(&args[1])?.to_u32()?); - let (len, e_ty) = args[0].layout.ty.simd_size_and_type(*self.tcx); + let (input, input_len) = self.operand_to_simd(&args[0])?; assert!( - index < len, - "index `{}` is out-of-bounds of vector type `{}` with length `{}`", + index < input_len, + "index `{}` must be in bounds of vector with length `{}`", index, - e_ty, - len - ); - assert_eq!( - e_ty, dest.layout.ty, - "Return type `{}` must match vector element type `{}`", - dest.layout.ty, e_ty + input_len ); - self.copy_op(&self.operand_index(&args[0], index)?, dest)?; + self.copy_op(&self.mplace_index(&input, index)?.into(), dest)?; } sym::likely | sym::unlikely | sym::black_box => { // These just return their argument diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index b6682b13ed216..de9e94ce2ac0c 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -437,6 +437,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }) } + /// Converts a repr(simd) operand into an operand where `place_index` accesses the SIMD elements. + /// Also returns the number of elements. + pub fn operand_to_simd( + &self, + base: &OpTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::PointerTag>, u64)> { + // Basically we just transmute this place into an array following simd_size_and_type. + // This only works in memory, but repr(simd) types should never be immediates anyway. + assert!(base.layout.ty.is_simd()); + self.mplace_to_simd(&base.assert_mem_place()) + } + /// Read from a local. Will not actually access the local if reading from a ZST. /// Will not access memory, instead an indirect `Operand` is returned. /// diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index d425b84bdaf26..d7f2853fc86f5 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -200,7 +200,7 @@ impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> { } } else { // Go through the layout. There are lots of types that support a length, - // e.g., SIMD types. + // e.g., SIMD types. (But not all repr(simd) types even have FieldsShape::Array!) match self.layout.fields { FieldsShape::Array { count, .. } => Ok(count), _ => bug!("len not supported on sized type {:?}", self.layout.ty), @@ -533,6 +533,22 @@ where }) } + /// Converts a repr(simd) place into a place where `place_index` accesses the SIMD elements. + /// Also returns the number of elements. + pub fn mplace_to_simd( + &self, + base: &MPlaceTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::PointerTag>, u64)> { + // Basically we just transmute this place into an array following simd_size_and_type. + // (Transmuting is okay since this is an in-memory place. We also double-check the size + // stays the same.) + let (len, e_ty) = base.layout.ty.simd_size_and_type(*self.tcx); + let array = self.tcx.mk_array(e_ty, len); + let layout = self.layout_of(array)?; + assert_eq!(layout.size, base.layout.size); + Ok((MPlaceTy { layout, ..*base }, len)) + } + /// Gets the place of a field inside the place, and also the field's type. /// Just a convenience function, but used quite a bit. /// This is the only projection that might have a side-effect: We cannot project @@ -594,6 +610,16 @@ where }) } + /// Converts a repr(simd) place into a place where `place_index` accesses the SIMD elements. + /// Also returns the number of elements. + pub fn place_to_simd( + &mut self, + base: &PlaceTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::PointerTag>, u64)> { + let mplace = self.force_allocation(base)?; + self.mplace_to_simd(&mplace) + } + /// Computes a place. You should only use this if you intend to write into this /// place; for reading, a more efficient alternative is `eval_place_for_read`. pub fn eval_place( diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 610f9bd8f82d7..c79e25f4781c8 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1805,10 +1805,13 @@ impl<'tcx> TyS<'tcx> { pub fn simd_size_and_type(&self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) { match self.kind() { Adt(def, substs) => { + assert!(def.repr.simd(), "`simd_size_and_type` called on non-SIMD type"); let variant = def.non_enum_variant(); let f0_ty = variant.fields[0].ty(tcx, substs); match f0_ty.kind() { + // If the first field is an array, we assume it is the only field and its + // elements are the SIMD components. Array(f0_elem_ty, f0_len) => { // FIXME(repr_simd): https://github.com/rust-lang/rust/pull/78863#discussion_r522784112 // The way we evaluate the `N` in `[T; N]` here only works since we use @@ -1816,6 +1819,8 @@ impl<'tcx> TyS<'tcx> { // if we use it in generic code. See the `simd-array-trait` ui test. (f0_len.eval_usize(tcx, ParamEnv::empty()) as u64, f0_elem_ty) } + // Otherwise, the fields of this Adt are the SIMD components (and we assume they + // all have the same type). _ => (variant.fields.len() as u64, f0_ty), } } diff --git a/src/test/ui/consts/const-eval/simd/insert_extract.rs b/src/test/ui/consts/const-eval/simd/insert_extract.rs index cae8fcf1068ad..a1cd24077c661 100644 --- a/src/test/ui/consts/const-eval/simd/insert_extract.rs +++ b/src/test/ui/consts/const-eval/simd/insert_extract.rs @@ -7,7 +7,8 @@ #[repr(simd)] struct i8x1(i8); #[repr(simd)] struct u16x2(u16, u16); -#[repr(simd)] struct f32x4(f32, f32, f32, f32); +// Make one of them an array type to ensure those also work. +#[repr(simd)] struct f32x4([f32; 4]); extern "platform-intrinsic" { #[rustc_const_stable(feature = "foo", since = "1.3.37")] @@ -38,12 +39,12 @@ fn main() { assert_eq!(Y1, 42); } { - const U: f32x4 = f32x4(13., 14., 15., 16.); + const U: f32x4 = f32x4([13., 14., 15., 16.]); const V: f32x4 = unsafe { simd_insert(U, 1_u32, 42_f32) }; - const X0: f32 = V.0; - const X1: f32 = V.1; - const X2: f32 = V.2; - const X3: f32 = V.3; + const X0: f32 = V.0[0]; + const X1: f32 = V.0[1]; + const X2: f32 = V.0[2]; + const X3: f32 = V.0[3]; const Y0: f32 = unsafe { simd_extract(V, 0) }; const Y1: f32 = unsafe { simd_extract(V, 1) }; const Y2: f32 = unsafe { simd_extract(V, 2) }; From 0304e16f3b357c3df48b25277127c658b5169fd4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 18 Nov 2021 11:05:30 -0500 Subject: [PATCH 07/12] CTFE SIMD: also test 1-element array --- src/test/ui/consts/const-eval/simd/insert_extract.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/test/ui/consts/const-eval/simd/insert_extract.rs b/src/test/ui/consts/const-eval/simd/insert_extract.rs index a1cd24077c661..a1d6c5e51b498 100644 --- a/src/test/ui/consts/const-eval/simd/insert_extract.rs +++ b/src/test/ui/consts/const-eval/simd/insert_extract.rs @@ -7,7 +7,8 @@ #[repr(simd)] struct i8x1(i8); #[repr(simd)] struct u16x2(u16, u16); -// Make one of them an array type to ensure those also work. +// Make some of them array types to ensure those also work. +#[repr(simd)] struct i8x1_arr([i8; 1]); #[repr(simd)] struct f32x4([f32; 4]); extern "platform-intrinsic" { @@ -26,6 +27,14 @@ fn main() { assert_eq!(X0, 42); assert_eq!(Y0, 42); } + { + const U: i8x1_arr = i8x1_arr([13]); + const V: i8x1_arr = unsafe { simd_insert(U, 0_u32, 42_i8) }; + const X0: i8 = V.0[0]; + const Y0: i8 = unsafe { simd_extract(V, 0) }; + assert_eq!(X0, 42); + assert_eq!(Y0, 42); + } { const U: u16x2 = u16x2(13, 14); const V: u16x2 = unsafe { simd_insert(U, 1_u32, 42_u16) }; From 214ad2f5b5ff529548ce13dabcda8d5841df0bd7 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 18 Nov 2021 16:15:12 -0700 Subject: [PATCH 08/12] rustdoc doctest: detect `fn main` after an unexpected semicolon The basic problem with this is that rustdoc, when hunting for `fn main`, will stop parsing after it reaches a fatal error. This unexpected semicolon was a fatal error, so in `src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.rs`, it would wrap the doctest in an implied main function, turning it into this: fn main() { struct S {}; fn main() { assert_eq!(0, 1); } } This, as it turns out, is totally valid, and it executes no assertions, so *it passes,* even though the user wanted it to execute the assertion. The Rust parser already has the ability to recover from these unexpected semicolons, but to do so, it needs to use the `parse_mod` function, so this commit changes it to do that. --- src/librustdoc/doctest.rs | 17 ++++++------- .../failed-doctest-extra-semicolon-on-item.rs | 18 ++++++++++++++ ...led-doctest-extra-semicolon-on-item.stdout | 24 +++++++++++++++++++ 3 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.rs create mode 100644 src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.stdout diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index c10eebf49fc8d..37db20aaefa8d 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1,4 +1,4 @@ -use rustc_ast as ast; +use rustc_ast::{self as ast, token}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_errors::{ColorConfig, ErrorReported, FatalError}; @@ -537,7 +537,6 @@ crate fn make_test( use rustc_errors::emitter::{Emitter, EmitterWriter}; use rustc_errors::Handler; use rustc_parse::maybe_new_parser_from_source_str; - use rustc_parse::parser::ForceCollect; use rustc_session::parse::ParseSess; use rustc_span::source_map::FilePathMapping; @@ -573,9 +572,9 @@ crate fn make_test( } }; - loop { - match parser.parse_item(ForceCollect::No) { - Ok(Some(item)) => { + match parser.parse_mod(&token::Eof) { + Ok((_attrs, items, _span)) => { + for item in items { if !found_main { if let ast::ItemKind::Fn(..) = item.kind { if item.ident.name == sym::main { @@ -607,11 +606,9 @@ crate fn make_test( break; } } - Ok(None) => break, - Err(mut e) => { - e.cancel(); - break; - } + } + Err(mut e) => { + e.cancel(); } } diff --git a/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.rs b/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.rs new file mode 100644 index 0000000000000..16d737106ea89 --- /dev/null +++ b/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.rs @@ -0,0 +1,18 @@ +// FIXME: if/when the output of the test harness can be tested on its own, this test should be +// adapted to use that, and that normalize line can go away + +// compile-flags:--test +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +// failure-status: 101 + +/// +/// +/// ```rust +/// struct S {}; // unexpected semicolon after struct def +/// +/// fn main() { +/// assert_eq!(0, 1); +/// } +/// ``` +mod m {} diff --git a/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.stdout b/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.stdout new file mode 100644 index 0000000000000..61468b6c7457b --- /dev/null +++ b/src/test/rustdoc-ui/failed-doctest-extra-semicolon-on-item.stdout @@ -0,0 +1,24 @@ + +running 1 test +test $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) ... FAILED + +failures: + +---- $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) stdout ---- +error: expected item, found `;` + --> $DIR/failed-doctest-extra-semicolon-on-item.rs:12:12 + | +LL | struct S {}; // unexpected semicolon after struct def + | ^ help: remove this semicolon + | + = help: braced struct declarations are not followed by a semicolon + +error: aborting due to previous error + +Couldn't compile the test. + +failures: + $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + From 592178cfcf6ef61d48691d1614143e7052291be8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 19 Nov 2021 10:20:49 +0100 Subject: [PATCH 09/12] Put back removed empty line --- src/doc/rustdoc/src/unstable-features.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 16532215c6f33..8da1d22a4d172 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -398,6 +398,7 @@ undocumented item: ```rust /// This item has documentation pub fn foo() {} + pub fn no_documentation() {} ``` From cdb0c29a9cf83db18906d7da7e2dbb581044a633 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 19 Nov 2021 19:13:53 +0300 Subject: [PATCH 10/12] Remove unnecessary doc links --- library/core/src/primitive_docs.rs | 2 -- library/std/src/primitive_docs.rs | 2 -- 2 files changed, 4 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index d919f8ee31e38..f47a30c9b5d7d 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1108,7 +1108,6 @@ mod prim_usize {} /// /// [`Deref`]: ops::Deref /// [`Borrow`]: borrow::Borrow -/// [`fmt::Pointer`]: fmt::Pointer /// /// `&mut T` references get all of the above except `Copy` and `Clone` (to prevent creating /// multiple simultaneous mutable borrows), plus the following, regardless of the type of its @@ -1136,7 +1135,6 @@ mod prim_usize {} /// * [`Send`] \(`&T` references also require T: [Sync]) /// /// [`std::fmt`]: fmt -/// [`fmt::Pointer`]: fmt::Pointer /// [`Hash`]: hash::Hash #[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))] /// diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index d919f8ee31e38..f47a30c9b5d7d 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -1108,7 +1108,6 @@ mod prim_usize {} /// /// [`Deref`]: ops::Deref /// [`Borrow`]: borrow::Borrow -/// [`fmt::Pointer`]: fmt::Pointer /// /// `&mut T` references get all of the above except `Copy` and `Clone` (to prevent creating /// multiple simultaneous mutable borrows), plus the following, regardless of the type of its @@ -1136,7 +1135,6 @@ mod prim_usize {} /// * [`Send`] \(`&T` references also require T: [Sync]) /// /// [`std::fmt`]: fmt -/// [`fmt::Pointer`]: fmt::Pointer /// [`Hash`]: hash::Hash #[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))] /// From a2d78573d396f8bf27da3ae0f2531ecb8649639c Mon Sep 17 00:00:00 2001 From: r00ster91 Date: Fri, 19 Nov 2021 18:14:18 +0100 Subject: [PATCH 11/12] Turn all 0x1b_u8 into '\x1b' or b'\x1b' --- library/core/src/char/methods.rs | 20 ++++++++++---------- library/core/src/num/mod.rs | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index d5ad0c385c701..7250dca2adfe4 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1250,7 +1250,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(uppercase_a.is_ascii_alphabetic()); /// assert!(uppercase_g.is_ascii_alphabetic()); @@ -1284,7 +1284,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(uppercase_a.is_ascii_uppercase()); /// assert!(uppercase_g.is_ascii_uppercase()); @@ -1318,7 +1318,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(!uppercase_a.is_ascii_lowercase()); /// assert!(!uppercase_g.is_ascii_lowercase()); @@ -1355,7 +1355,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(uppercase_a.is_ascii_alphanumeric()); /// assert!(uppercase_g.is_ascii_alphanumeric()); @@ -1389,7 +1389,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(!uppercase_a.is_ascii_digit()); /// assert!(!uppercase_g.is_ascii_digit()); @@ -1426,7 +1426,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(uppercase_a.is_ascii_hexdigit()); /// assert!(!uppercase_g.is_ascii_hexdigit()); @@ -1464,7 +1464,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(!uppercase_a.is_ascii_punctuation()); /// assert!(!uppercase_g.is_ascii_punctuation()); @@ -1498,7 +1498,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(uppercase_a.is_ascii_graphic()); /// assert!(uppercase_g.is_ascii_graphic()); @@ -1549,7 +1549,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(!uppercase_a.is_ascii_whitespace()); /// assert!(!uppercase_g.is_ascii_whitespace()); @@ -1585,7 +1585,7 @@ impl char { /// let percent = '%'; /// let space = ' '; /// let lf = '\n'; - /// let esc: char = 0x1b_u8.into(); + /// let esc = '\x1b'; /// /// assert!(!uppercase_a.is_ascii_control()); /// assert!(!uppercase_g.is_ascii_control()); diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index a8f2ded46594e..e3eab07b9df6d 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -428,7 +428,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(uppercase_a.is_ascii_alphabetic()); /// assert!(uppercase_g.is_ascii_alphabetic()); @@ -462,7 +462,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(uppercase_a.is_ascii_uppercase()); /// assert!(uppercase_g.is_ascii_uppercase()); @@ -496,7 +496,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(!uppercase_a.is_ascii_lowercase()); /// assert!(!uppercase_g.is_ascii_lowercase()); @@ -533,7 +533,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(uppercase_a.is_ascii_alphanumeric()); /// assert!(uppercase_g.is_ascii_alphanumeric()); @@ -567,7 +567,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(!uppercase_a.is_ascii_digit()); /// assert!(!uppercase_g.is_ascii_digit()); @@ -604,7 +604,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(uppercase_a.is_ascii_hexdigit()); /// assert!(!uppercase_g.is_ascii_hexdigit()); @@ -642,7 +642,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(!uppercase_a.is_ascii_punctuation()); /// assert!(!uppercase_g.is_ascii_punctuation()); @@ -676,7 +676,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(uppercase_a.is_ascii_graphic()); /// assert!(uppercase_g.is_ascii_graphic()); @@ -727,7 +727,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(!uppercase_a.is_ascii_whitespace()); /// assert!(!uppercase_g.is_ascii_whitespace()); @@ -763,7 +763,7 @@ impl u8 { /// let percent = b'%'; /// let space = b' '; /// let lf = b'\n'; - /// let esc = 0x1b_u8; + /// let esc = b'\x1b'; /// /// assert!(!uppercase_a.is_ascii_control()); /// assert!(!uppercase_g.is_ascii_control()); From 0ae053a48122d29caa6d738dbcbd98888330d160 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Fri, 19 Nov 2021 15:54:05 -0500 Subject: [PATCH 12/12] rustdoc: Fix some unescaped HTML tags in docs They were being interpreted literally. --- src/librustdoc/externalfiles.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 302fc5a677771..6ed911b8d2409 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -8,13 +8,13 @@ use serde::Serialize; #[derive(Clone, Debug, Serialize)] crate struct ExternalHtml { - /// Content that will be included inline in the section of a + /// Content that will be included inline in the `` section of a /// rendered Markdown file or generated documentation crate in_header: String, - /// Content that will be included inline between and the content of + /// Content that will be included inline between `` and the content of /// a rendered Markdown file or generated documentation crate before_content: String, - /// Content that will be included inline between the content and of + /// Content that will be included inline between the content and `` of /// a rendered Markdown file or generated documentation crate after_content: String, }