diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 5e7bbc0113271..9bbb42eb01961 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -419,48 +419,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/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());
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 0de9126dab2fe..f47a30c9b5d7d 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1104,11 +1104,10 @@ 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
///
/// `&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 +1123,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 +1132,9 @@ 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
/// [`Hash`]: hash::Hash
#[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))]
///
@@ -1150,7 +1149,6 @@ mod prim_usize {}
/// * [`ExactSizeIterator`]
/// * [`FusedIterator`]
/// * [`TrustedLen`]
-/// * [`Send`] \(note that `&T` references only get `Send` if T: [Sync]
)
/// * [`io::Write`]
/// * [`Read`]
/// * [`Seek`]
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 0de9126dab2fe..f47a30c9b5d7d 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -1104,11 +1104,10 @@ 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
///
/// `&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 +1123,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 +1132,9 @@ 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
/// [`Hash`]: hash::Hash
#[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))]
///
@@ -1150,7 +1149,6 @@ mod prim_usize {}
/// * [`ExactSizeIterator`]
/// * [`FusedIterator`]
/// * [`TrustedLen`]
-/// * [`Send`] \(note that `&T` references only get `Send` if T: [Sync]
)
/// * [`io::Write`]
/// * [`Read`]
/// * [`Seek`]
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() {}
```
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/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
{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("{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, "