Auto merge of #91064 - matthiaskrgr:rollup-2ijidpt, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #88361 (Makes docs for references a little less confusing) - #90089 (Improve display of enum variants) - #90956 (Add a regression test for #87573) - #90999 (fix CTFE/Miri simd_insert/extract on array-style repr(simd) types) - #91026 (rustdoc doctest: detect `fn main` after an unexpected semicolon) - #91035 (Put back removed empty line) - #91044 (Turn all 0x1b_u8 into '\x1b' or b'\x1b') - #91054 (rustdoc: Fix some unescaped HTML tags in docs) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
3b65165ab7
21 changed files with 293 additions and 129 deletions
|
|
@ -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
|
||||
input_len
|
||||
);
|
||||
assert_eq!(
|
||||
e_ty, dest.layout.ty,
|
||||
"Return type `{}` must match vector element type `{}`",
|
||||
dest.layout.ty, e_ty
|
||||
);
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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 <code>T: [Sync]</code>)
|
||||
///
|
||||
/// [`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 <code>T: [Sync]</code>)
|
||||
/// * [`io::Write`]
|
||||
/// * [`Read`]
|
||||
/// * [`Seek`]
|
||||
|
|
|
|||
|
|
@ -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 <code>T: [Sync]</code>)
|
||||
///
|
||||
/// [`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 <code>T: [Sync]</code>)
|
||||
/// * [`io::Write`]
|
||||
/// * [`Read`]
|
||||
/// * [`Seek`]
|
||||
|
|
|
|||
|
|
@ -398,6 +398,7 @@ undocumented item:
|
|||
```rust
|
||||
/// This item has documentation
|
||||
pub fn foo() {}
|
||||
|
||||
pub fn no_documentation() {}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ use serde::Serialize;
|
|||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
crate struct ExternalHtml {
|
||||
/// Content that will be included inline in the <head> section of a
|
||||
/// Content that will be included inline in the `<head>` section of a
|
||||
/// rendered Markdown file or generated documentation
|
||||
crate in_header: String,
|
||||
/// Content that will be included inline between <body> and the content of
|
||||
/// Content that will be included inline between `<body>` 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 </body> of
|
||||
/// Content that will be included inline between the content and `</body>` of
|
||||
/// a rendered Markdown file or generated documentation
|
||||
crate after_content: String,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
"<div id=\"{id}\" class=\"variant small-section-header\">\
|
||||
"<h3 id=\"{id}\" class=\"variant small-section-header\">\
|
||||
<a href=\"#{id}\" class=\"anchor field\"></a>\
|
||||
<code>{name}",
|
||||
id = id,
|
||||
|
|
@ -1093,9 +1093,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
|
|||
}
|
||||
w.write_str("</code>");
|
||||
render_stability_since(w, variant, it, cx.tcx());
|
||||
w.write_str("</div>");
|
||||
document(w, cx, variant, Some(it), HeadingOffset::H3);
|
||||
document_non_exhaustive(w, variant);
|
||||
w.write_str("</h3>");
|
||||
|
||||
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, "<div class=\"sub-variant\" id=\"{id}\">", id = variant_id);
|
||||
write!(
|
||||
w,
|
||||
"<h3>{extra}Fields of <b>{name}</b></h3><div>",
|
||||
extra = extra,
|
||||
name = variant.name.as_ref().unwrap(),
|
||||
);
|
||||
write!(w, "<h4>{extra}Fields</h4>", 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,
|
||||
"<span id=\"{id}\" class=\"variant small-section-header\">\
|
||||
"<div class=\"sub-variant-field\">\
|
||||
<span id=\"{id}\" class=\"variant small-section-header\">\
|
||||
<a href=\"#{id}\" class=\"anchor field\"></a>\
|
||||
<code>{f}: {t}</code>\
|
||||
</span>",
|
||||
|
|
@ -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, "</div>");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
w.write_str("</div></div>");
|
||||
w.write_str("</div>");
|
||||
}
|
||||
|
||||
document(w, cx, variant, Some(it), HeadingOffset::H4);
|
||||
}
|
||||
}
|
||||
let def_id = it.def_id.expect_def_id();
|
||||
|
|
|
|||
|
|
@ -1102,25 +1102,28 @@ a.test-arrow:hover{
|
|||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.sub-variant, .sub-variant > h3 {
|
||||
margin-top: 0px !important;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
#main .sub-variant > h3 {
|
||||
font-size: 15px;
|
||||
margin-left: 25px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.sub-variant > div {
|
||||
margin-left: 20px;
|
||||
h3.variant {
|
||||
font-weight: 600;
|
||||
font-size: 1.1em;
|
||||
margin-bottom: 10px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.sub-variant > div > span {
|
||||
display: block;
|
||||
position: relative;
|
||||
.sub-variant h4 {
|
||||
font-size: 1em;
|
||||
font-weight: 400;
|
||||
border-bottom: none;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.sub-variant {
|
||||
margin-left: 24px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.sub-variant > .sub-variant-field {
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
.toggle-label {
|
||||
|
|
|
|||
|
|
@ -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: ("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: ("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#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: ("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: ("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: ("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: ("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"})
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
/// <https://github.com/rust-lang/rust/issues/91014>
|
||||
///
|
||||
/// ```rust
|
||||
/// struct S {}; // unexpected semicolon after struct def
|
||||
///
|
||||
/// fn main() {
|
||||
/// assert_eq!(0, 1);
|
||||
/// }
|
||||
/// ```
|
||||
mod m {}
|
||||
|
|
@ -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
|
||||
|
||||
40
src/test/rustdoc/enum-headings.rs
Normal file
40
src/test/rustdoc/enum-headings.rs
Normal file
|
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@
|
|||
|
||||
#[repr(simd)] struct i8x1(i8);
|
||||
#[repr(simd)] struct u16x2(u16, u16);
|
||||
#[repr(simd)] struct f32x4(f32, f32, f32, f32);
|
||||
// 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" {
|
||||
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
|
||||
|
|
@ -25,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) };
|
||||
|
|
@ -38,12 +48,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) };
|
||||
|
|
|
|||
28
src/test/ui/lang-items/issue-87573.rs
Normal file
28
src/test/ui/lang-items/issue-87573.rs
Normal file
|
|
@ -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(){}
|
||||
21
src/test/ui/lang-items/issue-87573.stderr
Normal file
21
src/test/ui/lang-items/issue-87573.stderr
Normal file
|
|
@ -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`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue