Auto merge of #89608 - Manishearth:rollup-m7kd76f, r=Manishearth

Rollup of 12 pull requests

Successful merges:

 - #87601 (Add functions to add unsigned and signed integers)
 - #88523 (Expand documentation for `FpCategory`.)
 - #89050 (refactor: VecDeques Drain fields to private)
 - #89245 (refactor: make VecDeque's IterMut fields module-private, not just crate-private)
 - #89324 (Rename `std:🧵:available_conccurrency` to `std:🧵:available_parallelism`)
 - #89329 (print-type-sizes: skip field printing for primitives)
 - #89501 (Note specific regions involved in 'borrowed data escapes' error)
 - #89506 (librustdoc: Use correct heading levels.)
 - #89528 (Fix suggestion to borrow when casting from pointer to reference)
 - #89531 (library std, libc dependency update)
 - #89588 (Add a test for generic_const_exprs)
 - #89591 (fix: alloc-optimisation is only for rust llvm)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-10-06 20:17:28 +00:00
commit 0eabf25b90
69 changed files with 984 additions and 249 deletions

View File

@ -1879,9 +1879,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.99"
version = "0.2.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
dependencies = [
"rustc-std-workspace-core",
]

View File

@ -498,6 +498,27 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
diag.span_label(*span, format!("`{}` escapes the {} body here", fr_name, escapes_from));
}
// Only show an extra note if we can find an 'error region' for both of the region
// variables. This avoids showing a noisy note that just mentions 'synthetic' regions
// that don't help the user understand the error.
if self.to_error_region(errci.fr).is_some()
&& self.to_error_region(errci.outlived_fr).is_some()
{
let fr_region_name = self.give_region_a_name(errci.fr).unwrap();
fr_region_name.highlight_region_name(&mut diag);
let outlived_fr_region_name = self.give_region_a_name(errci.outlived_fr).unwrap();
outlived_fr_region_name.highlight_region_name(&mut diag);
diag.span_label(
*span,
format!(
"{}requires that `{}` must outlive `{}`",
category.description(),
fr_region_name,
outlived_fr_region_name,
),
);
}
diag
}

View File

@ -1826,8 +1826,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
match layout.variants {
Variants::Single { index } => {
debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variants[index].ident);
if !adt_def.variants.is_empty() {
if !adt_def.variants.is_empty() && layout.fields != FieldsShape::Primitive {
debug!(
"print-type-size `{:#?}` variant {}",
layout, adt_def.variants[index].ident
);
let variant_def = &adt_def.variants[index];
let fields: Vec<_> = variant_def.fields.iter().map(|f| f.ident.name).collect();
record(

View File

@ -351,7 +351,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
);
let mut sugg = None;
let mut sugg_mutref = false;
if let ty::Ref(reg, _, mutbl) = *self.cast_ty.kind() {
if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() {
if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind() {
if fcx
.try_coerce(
@ -366,7 +366,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
)
.is_ok()
{
sugg = Some(format!("&{}*", mutbl.prefix_str()));
sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty));
}
} else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind() {
if expr_mutbl == Mutability::Not
@ -400,7 +400,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
)
.is_ok()
{
sugg = Some(format!("&{}", mutbl.prefix_str()));
sugg = Some((format!("&{}", mutbl.prefix_str()), false));
}
} else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind() {
if fcx
@ -416,19 +416,47 @@ impl<'a, 'tcx> CastCheck<'tcx> {
)
.is_ok()
{
sugg = Some(format!("&{}", mutbl.prefix_str()));
sugg = Some((format!("&{}", mutbl.prefix_str()), false));
}
}
if sugg_mutref {
err.span_label(self.span, "invalid cast");
err.span_note(self.expr.span, "this reference is immutable");
err.span_note(self.cast_span, "trying to cast to a mutable reference type");
} else if let Some(sugg) = sugg {
} else if let Some((sugg, remove_cast)) = sugg {
err.span_label(self.span, "invalid cast");
err.span_suggestion_verbose(
self.expr.span.shrink_to_lo(),
let has_parens = fcx
.tcx
.sess
.source_map()
.span_to_snippet(self.expr.span)
.map_or(false, |snip| snip.starts_with("("));
// Very crude check to see whether the expression must be wrapped
// in parentheses for the suggestion to work (issue #89497).
// Can/should be extended in the future.
let needs_parens = !has_parens
&& match self.expr.kind {
hir::ExprKind::Cast(..) => true,
_ => false,
};
let mut suggestion = vec![(self.expr.span.shrink_to_lo(), sugg)];
if needs_parens {
suggestion[0].1 += "(";
suggestion.push((self.expr.span.shrink_to_hi(), ")".to_string()));
}
if remove_cast {
suggestion.push((
self.expr.span.shrink_to_hi().to(self.cast_span),
String::new(),
));
}
err.multipart_suggestion_verbose(
"consider borrowing the value",
sugg,
suggestion,
Applicability::MachineApplicable,
);
} else if !matches!(

View File

@ -18,10 +18,21 @@ pub struct Drain<
T: 'a,
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
> {
pub(crate) after_tail: usize,
pub(crate) after_head: usize,
pub(crate) iter: Iter<'a, T>,
pub(crate) deque: NonNull<VecDeque<T, A>>,
after_tail: usize,
after_head: usize,
iter: Iter<'a, T>,
deque: NonNull<VecDeque<T, A>>,
}
impl<'a, T, A: Allocator> Drain<'a, T, A> {
pub(super) unsafe fn new(
after_tail: usize,
after_head: usize,
iter: Iter<'a, T>,
deque: NonNull<VecDeque<T, A>>,
) -> Self {
Drain { after_tail, after_head, iter, deque }
}
}
#[stable(feature = "collection_debug", since = "1.17.0")]

View File

@ -13,10 +13,21 @@ use super::{count, wrap_index, RingSlices};
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IterMut<'a, T: 'a> {
// Internal safety invariant: the entire slice is dereferencable.
pub(crate) ring: *mut [T],
pub(crate) tail: usize,
pub(crate) head: usize,
pub(crate) phantom: PhantomData<&'a mut [T]>,
ring: *mut [T],
tail: usize,
head: usize,
phantom: PhantomData<&'a mut [T]>,
}
impl<'a, T> IterMut<'a, T> {
pub(super) unsafe fn new(
ring: *mut [T],
tail: usize,
head: usize,
phantom: PhantomData<&'a mut [T]>,
) -> Self {
IterMut { ring, tail, head, phantom }
}
}
// SAFETY: we do nothing thread-local and there is no interior mutability,

View File

@ -1000,12 +1000,9 @@ impl<T, A: Allocator> VecDeque<T, A> {
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
// SAFETY: The internal `IterMut` safety invariant is established because the
// `ring` we create is a dereferencable slice for lifetime '_.
IterMut {
tail: self.tail,
head: self.head,
ring: ptr::slice_from_raw_parts_mut(self.ptr(), self.cap()),
phantom: PhantomData,
}
let ring = ptr::slice_from_raw_parts_mut(self.ptr(), self.cap());
unsafe { IterMut::new(ring, self.tail, self.head, PhantomData) }
}
/// Returns a pair of slices which contain, in order, the contents of the
@ -1192,12 +1189,9 @@ impl<T, A: Allocator> VecDeque<T, A> {
// SAFETY: The internal `IterMut` safety invariant is established because the
// `ring` we create is a dereferencable slice for lifetime '_.
IterMut {
tail,
head,
ring: ptr::slice_from_raw_parts_mut(self.ptr(), self.cap()),
phantom: PhantomData,
}
let ring = ptr::slice_from_raw_parts_mut(self.ptr(), self.cap());
unsafe { IterMut::new(ring, tail, head, PhantomData) }
}
/// Creates a draining iterator that removes the specified range in the
@ -1269,19 +1263,17 @@ impl<T, A: Allocator> VecDeque<T, A> {
// the drain is complete and the Drain destructor is run.
self.head = drain_tail;
Drain {
deque: NonNull::from(&mut *self),
after_tail: drain_head,
after_head: head,
iter: Iter {
tail: drain_tail,
head: drain_head,
// Crucially, we only create shared references from `self` here and read from
// it. We do not write to `self` nor reborrow to a mutable reference.
// Hence the raw pointer we created above, for `deque`, remains valid.
ring: unsafe { self.buffer_as_slice() },
},
}
let deque = NonNull::from(&mut *self);
let iter = Iter {
tail: drain_tail,
head: drain_head,
// Crucially, we only create shared references from `self` here and read from
// it. We do not write to `self` nor reborrow to a mutable reference.
// Hence the raw pointer we created above, for `deque`, remains valid.
ring: unsafe { self.buffer_as_slice() },
};
unsafe { Drain::new(drain_head, head, iter, deque) }
}
/// Clears the `VecDeque`, removing all values.

View File

@ -142,6 +142,7 @@
#![feature(link_llvm_intrinsics)]
#![feature(llvm_asm)]
#![feature(min_specialization)]
#![feature(mixed_integer_ops)]
#![cfg_attr(not(bootstrap), feature(must_not_suspend))]
#![feature(negative_impls)]
#![feature(never_type)]

View File

@ -433,6 +433,28 @@ macro_rules! int_impl {
unsafe { intrinsics::unchecked_add(self, rhs) }
}
/// Checked addition with an unsigned integer. Computes `self + rhs`,
/// returning `None` if overflow occurred.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_unsigned(2), Some(3));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_unsigned(3), None);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn checked_add_unsigned(self, rhs: $UnsignedT) -> Option<Self> {
let (a, b) = self.overflowing_add_unsigned(rhs);
if unlikely!(b) {None} else {Some(a)}
}
/// Checked integer subtraction. Computes `self - rhs`, returning `None` if
/// overflow occurred.
///
@ -479,6 +501,28 @@ macro_rules! int_impl {
unsafe { intrinsics::unchecked_sub(self, rhs) }
}
/// Checked subtraction with an unsigned integer. Computes `self - rhs`,
/// returning `None` if overflow occurred.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_unsigned(2), Some(-1));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub_unsigned(3), None);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn checked_sub_unsigned(self, rhs: $UnsignedT) -> Option<Self> {
let (a, b) = self.overflowing_sub_unsigned(rhs);
if unlikely!(b) {None} else {Some(a)}
}
/// Checked integer multiplication. Computes `self * rhs`, returning `None` if
/// overflow occurred.
///
@ -826,6 +870,32 @@ macro_rules! int_impl {
intrinsics::saturating_add(self, rhs)
}
/// Saturating addition with an unsigned integer. Computes `self + rhs`,
/// saturating at the numeric bounds instead of overflowing.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_unsigned(2), 3);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_add_unsigned(100), ", stringify!($SelfT), "::MAX);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn saturating_add_unsigned(self, rhs: $UnsignedT) -> Self {
// Overflow can only happen at the upper bound
// We cannot use `unwrap_or` here because it is not `const`
match self.checked_add_unsigned(rhs) {
Some(x) => x,
None => Self::MAX,
}
}
/// Saturating integer subtraction. Computes `self - rhs`, saturating at the
/// numeric bounds instead of overflowing.
///
@ -847,6 +917,32 @@ macro_rules! int_impl {
intrinsics::saturating_sub(self, rhs)
}
/// Saturating subtraction with an unsigned integer. Computes `self - rhs`,
/// saturating at the numeric bounds instead of overflowing.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_sub_unsigned(127), -27);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub_unsigned(100), ", stringify!($SelfT), "::MIN);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn saturating_sub_unsigned(self, rhs: $UnsignedT) -> Self {
// Overflow can only happen at the lower bound
// We cannot use `unwrap_or` here because it is not `const`
match self.checked_sub_unsigned(rhs) {
Some(x) => x,
None => Self::MIN,
}
}
/// Saturating integer negation. Computes `-self`, returning `MAX` if `self == MIN`
/// instead of overflowing.
///
@ -1002,6 +1098,27 @@ macro_rules! int_impl {
intrinsics::wrapping_add(self, rhs)
}
/// Wrapping (modular) addition with an unsigned integer. Computes
/// `self + rhs`, wrapping around at the boundary of the type.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_add_unsigned(27), 127);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add_unsigned(2), ", stringify!($SelfT), "::MIN + 1);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
pub const fn wrapping_add_unsigned(self, rhs: $UnsignedT) -> Self {
self.wrapping_add(rhs as Self)
}
/// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the
/// boundary of the type.
///
@ -1022,6 +1139,27 @@ macro_rules! int_impl {
intrinsics::wrapping_sub(self, rhs)
}
/// Wrapping (modular) subtraction with an unsigned integer. Computes
/// `self - rhs`, wrapping around at the boundary of the type.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".wrapping_sub_unsigned(127), -127);")]
#[doc = concat!("assert_eq!((-2", stringify!($SelfT), ").wrapping_sub_unsigned(", stringify!($UnsignedT), "::MAX), -1);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
pub const fn wrapping_sub_unsigned(self, rhs: $UnsignedT) -> Self {
self.wrapping_sub(rhs as Self)
}
/// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at
/// the boundary of the type.
///
@ -1372,6 +1510,33 @@ macro_rules! int_impl {
(sum as $SelfT, carry)
}
/// Calculates `self` + `rhs` with an unsigned `rhs`
///
/// Returns a tuple of the addition along with a boolean indicating
/// whether an arithmetic overflow would occur. If an overflow would
/// have occurred then the wrapped value is returned.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_unsigned(2), (3, false));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN).overflowing_add_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MAX, false));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_unsigned(3), (", stringify!($SelfT), "::MIN, true));")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn overflowing_add_unsigned(self, rhs: $UnsignedT) -> (Self, bool) {
let rhs = rhs as Self;
let (res, overflowed) = self.overflowing_add(rhs);
(res, overflowed ^ (rhs < 0))
}
/// Calculates `self` - `rhs`
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow
@ -1423,6 +1588,33 @@ macro_rules! int_impl {
(sum as $SelfT, borrow)
}
/// Calculates `self` - `rhs` with an unsigned `rhs`
///
/// Returns a tuple of the subtraction along with a boolean indicating
/// whether an arithmetic overflow would occur. If an overflow would
/// have occurred then the wrapped value is returned.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_unsigned(2), (-1, false));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX).overflowing_sub_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MIN, false));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).overflowing_sub_unsigned(3), (", stringify!($SelfT), "::MAX, true));")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn overflowing_sub_unsigned(self, rhs: $UnsignedT) -> (Self, bool) {
let rhs = rhs as Self;
let (res, overflowed) = self.overflowing_sub(rhs);
(res, overflowed ^ (rhs < 0))
}
/// Calculates the multiplication of `self` and `rhs`.
///
/// Returns a tuple of the multiplication along with a boolean indicating whether an arithmetic overflow

View File

@ -245,7 +245,7 @@ const ASCII_CASE_MASK: u8 = 0b0010_0000;
#[lang = "u8"]
impl u8 {
widening_impl! { u8, u16, 8 }
uint_impl! { u8, u8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
uint_impl! { u8, u8, i8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
"[0x12]", "", "" }
/// Checks if the value is within the ASCII range.
@ -779,21 +779,21 @@ impl u8 {
#[lang = "u16"]
impl u16 {
widening_impl! { u16, u32, 16 }
uint_impl! { u16, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
uint_impl! { u16, u16, i16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
"[0x34, 0x12]", "[0x12, 0x34]", "", "" }
}
#[lang = "u32"]
impl u32 {
widening_impl! { u32, u64, 32 }
uint_impl! { u32, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
uint_impl! { u32, u32, i32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
}
#[lang = "u64"]
impl u64 {
widening_impl! { u64, u128, 64 }
uint_impl! { u64, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
uint_impl! { u64, u64, i64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
@ -802,7 +802,7 @@ impl u64 {
#[lang = "u128"]
impl u128 {
uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, 16,
uint_impl! { u128, u128, i128, 128, 340282366920938463463374607431768211455, 16,
"0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
"0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48",
"[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
@ -816,7 +816,7 @@ impl u128 {
#[lang = "usize"]
impl usize {
widening_impl! { usize, u32, 16 }
uint_impl! { usize, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
uint_impl! { usize, u16, isize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
"[0x34, 0x12]", "[0x12, 0x34]",
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
}
@ -824,7 +824,7 @@ impl usize {
#[lang = "usize"]
impl usize {
widening_impl! { usize, u64, 32 }
uint_impl! { usize, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
uint_impl! { usize, u32, isize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
}
@ -833,7 +833,7 @@ impl usize {
#[lang = "usize"]
impl usize {
widening_impl! { usize, u128, 64 }
uint_impl! { usize, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
uint_impl! { usize, u64, isize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
@ -865,23 +865,41 @@ impl usize {
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum FpCategory {
/// "Not a Number", often obtained by dividing by zero.
/// NaN (not a number): this value results from calculations like `(-1.0).sqrt()`.
///
/// See [the documentation for `f32`](f32) for more information on the unusual properties
/// of NaN.
#[stable(feature = "rust1", since = "1.0.0")]
Nan,
/// Positive or negative infinity.
/// Positive or negative infinity, which often results from dividing a nonzero number
/// by zero.
#[stable(feature = "rust1", since = "1.0.0")]
Infinite,
/// Positive or negative zero.
///
/// See [the documentation for `f32`](f32) for more information on the signedness of zeroes.
#[stable(feature = "rust1", since = "1.0.0")]
Zero,
/// De-normalized floating point representation (less precise than `Normal`).
/// “Subnormal” or “denormal” floating point representation (less precise, relative to
/// their magnitude, than [`Normal`]).
///
/// Subnormal numbers are larger in magnitude than [`Zero`] but smaller in magnitude than all
/// [`Normal`] numbers.
///
/// [`Normal`]: Self::Normal
/// [`Zero`]: Self::Zero
#[stable(feature = "rust1", since = "1.0.0")]
Subnormal,
/// A regular floating point number.
/// A regular floating point number, not any of the exceptional categories.
///
/// The smallest positive normal numbers are [`f32::MIN_POSITIVE`] and [`f64::MIN_POSITIVE`],
/// and the largest positive normal numbers are [`f32::MAX`] and [`f64::MAX`]. (Unlike signed
/// integers, floating point numbers are symmetric in their range, so negating any of these
/// constants will produce their negative counterpart.)
#[stable(feature = "rust1", since = "1.0.0")]
Normal,
}

View File

@ -1,5 +1,5 @@
macro_rules! uint_impl {
($SelfT:ty, $ActualT:ident, $BITS:expr, $MaxV:expr,
($SelfT:ty, $ActualT:ident, $SignedT:ident, $BITS:expr, $MaxV:expr,
$rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
$reversed:expr, $le_bytes:expr, $be_bytes:expr,
$to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => {
@ -442,6 +442,29 @@ macro_rules! uint_impl {
unsafe { intrinsics::unchecked_add(self, rhs) }
}
/// Checked addition with a signed integer. Computes `self + rhs`,
/// returning `None` if overflow occurred.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(2), Some(3));")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(-2), None);")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_signed(3), None);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn checked_add_signed(self, rhs: $SignedT) -> Option<Self> {
let (a, b) = self.overflowing_add_signed(rhs);
if unlikely!(b) {None} else {Some(a)}
}
/// Checked integer subtraction. Computes `self - rhs`, returning
/// `None` if overflow occurred.
///
@ -995,6 +1018,35 @@ macro_rules! uint_impl {
intrinsics::saturating_add(self, rhs)
}
/// Saturating addition with a signed integer. Computes `self + rhs`,
/// saturating at the numeric bounds instead of overflowing.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(2), 3);")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(-2), 0);")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_add_signed(4), ", stringify!($SelfT), "::MAX);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn saturating_add_signed(self, rhs: $SignedT) -> Self {
let (res, overflow) = self.overflowing_add(rhs as Self);
if overflow == (rhs < 0) {
res
} else if overflow {
Self::MAX
} else {
0
}
}
/// Saturating integer subtraction. Computes `self - rhs`, saturating
/// at the numeric bounds instead of overflowing.
///
@ -1111,6 +1163,28 @@ macro_rules! uint_impl {
intrinsics::wrapping_add(self, rhs)
}
/// Wrapping (modular) addition with a signed integer. Computes
/// `self + rhs`, wrapping around at the boundary of the type.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(2), 3);")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(-2), ", stringify!($SelfT), "::MAX);")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_add_signed(4), 1);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn wrapping_add_signed(self, rhs: $SignedT) -> Self {
self.wrapping_add(rhs as Self)
}
/// Wrapping (modular) subtraction. Computes `self - rhs`,
/// wrapping around at the boundary of the type.
///
@ -1435,6 +1509,32 @@ macro_rules! uint_impl {
(c, b | d)
}
/// Calculates `self` + `rhs` with a signed `rhs`
///
/// Returns a tuple of the addition along with a boolean indicating
/// whether an arithmetic overflow would occur. If an overflow would
/// have occurred then the wrapped value is returned.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(2), (3, false));")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(-2), (", stringify!($SelfT), "::MAX, true));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_signed(4), (1, true));")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn overflowing_add_signed(self, rhs: $SignedT) -> (Self, bool) {
let (res, overflowed) = self.overflowing_add(rhs as Self);
(res, overflowed ^ (rhs < 0))
}
/// Calculates `self` - `rhs`
///
/// Returns a tuple of the subtraction along with a boolean indicating

View File

@ -15,7 +15,7 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core" }
libc = { version = "0.2.99", default-features = false, features = ['rustc-dep-of-std'] }
libc = { version = "0.2.103", default-features = false, features = ['rustc-dep-of-std'] }
compiler_builtins = { version = "0.1.44" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }

View File

@ -292,12 +292,7 @@ where
SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n),
SeekFrom::Current(n) => (self.pos, n),
};
let new_pos = if offset >= 0 {
base_pos.checked_add(offset as u64)
} else {
base_pos.checked_sub((offset.wrapping_neg()) as u64)
};
match new_pos {
match base_pos.checked_add_signed(offset) {
Some(n) => {
self.pos = n;
Ok(self.pos)

View File

@ -297,6 +297,7 @@
#![feature(maybe_uninit_slice)]
#![feature(maybe_uninit_uninit_array)]
#![feature(min_specialization)]
#![feature(mixed_integer_ops)]
#![cfg_attr(not(bootstrap), feature(must_not_suspend))]
#![feature(needs_panic_runtime)]
#![feature(negative_impls)]

View File

@ -97,7 +97,7 @@ impl Thread {
}
}
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
unsupported()
}

View File

@ -137,7 +137,7 @@ impl Thread {
}
}
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
unsupported()
}

View File

@ -263,7 +263,7 @@ impl Drop for Thread {
}
}
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
cfg_if::cfg_if! {
if #[cfg(any(
target_os = "android",

View File

@ -31,7 +31,7 @@ impl Thread {
}
}
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
unsupported()
}

View File

@ -64,7 +64,7 @@ impl Thread {
}
}
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
unsupported()
}

View File

@ -40,7 +40,7 @@ impl Thread {
pub fn join(self) {}
}
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
unsupported()
}

View File

@ -100,7 +100,7 @@ impl Thread {
}
}
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
let res = unsafe {
let mut sysinfo: c::SYSTEM_INFO = crate::mem::zeroed();
c::GetSystemInfo(&mut sysinfo);

View File

@ -1453,12 +1453,14 @@ fn _assert_sync_and_send() {
///
/// ```
/// # #![allow(dead_code)]
/// #![feature(available_concurrency)]
/// #![feature(available_parallelism)]
/// use std::thread;
///
/// let count = thread::available_concurrency().map(|n| n.get()).unwrap_or(1);
/// let count = thread::available_parallelism().map(|n| n.get()).unwrap_or(1);
/// ```
#[unstable(feature = "available_concurrency", issue = "74479")]
pub fn available_concurrency() -> io::Result<NonZeroUsize> {
imp::available_concurrency()
#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`.
#[doc(alias = "available_concurrency")] // Alias for a name we gave this API on unstable.
#[unstable(feature = "available_parallelism", issue = "74479")]
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
imp::available_parallelism()
}

View File

@ -9,6 +9,6 @@ pub fn get_concurrency() -> usize {
_ => panic!("RUST_TEST_THREADS is `{}`, should be a positive integer.", value),
}
} else {
thread::available_concurrency().map(|n| n.get()).unwrap_or(1)
thread::available_parallelism().map(|n| n.get()).unwrap_or(1)
}
}

View File

@ -23,7 +23,7 @@
#![feature(libc)]
#![feature(rustc_private)]
#![feature(nll)]
#![feature(available_concurrency)]
#![feature(available_parallelism)]
#![feature(bench_black_box)]
#![feature(internal_output_capture)]
#![feature(panic_unwind)]

View File

@ -161,7 +161,7 @@ The following options affect how tests are executed.
Sets the number of threads to use for running tests in parallel. By default,
uses the amount of concurrency available on the hardware as indicated by
[`available_concurrency`].
[`available_parallelism`].
This can also be specified with the `RUST_TEST_THREADS` environment variable.
@ -265,7 +265,7 @@ Experimental support for using custom test harnesses is available on the
[`--test` option]: ../command-line-arguments.md#option-test
[`-Z panic-abort-tests`]: https://github.com/rust-lang/rust/issues/67650
[`available_concurrency`]: ../../std/thread/fn.available_concurrency.html
[`available_parallelism`]: ../../std/thread/fn.available_parallelism.html
[`cargo test`]: ../../cargo/commands/cargo-test.html
[`libtest`]: ../../test/index.html
[`main` function]: ../../reference/crates-and-source-files.html#main-functions

View File

@ -1,4 +1,4 @@
use crate::html::markdown::{ErrorCodes, IdMap, Markdown, Playground};
use crate::html::markdown::{ErrorCodes, HeadingOffset, IdMap, Markdown, Playground};
use crate::rustc_span::edition::Edition;
use std::fs;
use std::path::Path;
@ -39,14 +39,32 @@ impl ExternalHtml {
let bc = format!(
"{}{}",
bc,
Markdown(&m_bc, &[], id_map, codes, edition, playground).into_string()
Markdown {
content: &m_bc,
links: &[],
ids: id_map,
error_codes: codes,
edition,
playground,
heading_offset: HeadingOffset::H2,
}
.into_string()
);
let ac = load_external_files(after_content, diag)?;
let m_ac = load_external_files(md_after_content, diag)?;
let ac = format!(
"{}{}",
ac,
Markdown(&m_ac, &[], id_map, codes, edition, playground).into_string()
Markdown {
content: &m_ac,
links: &[],
ids: id_map,
error_codes: codes,
edition,
playground,
heading_offset: HeadingOffset::H2,
}
.into_string()
);
Some(ExternalHtml { in_header: ih, before_content: bc, after_content: ac })
}

View File

@ -8,11 +8,19 @@
//! extern crate rustc_span;
//!
//! use rustc_span::edition::Edition;
//! use rustdoc::html::markdown::{IdMap, Markdown, ErrorCodes};
//! use rustdoc::html::markdown::{HeadingOffset, IdMap, Markdown, ErrorCodes};
//!
//! let s = "My *markdown* _text_";
//! let mut id_map = IdMap::new();
//! let md = Markdown(s, &[], &mut id_map, ErrorCodes::Yes, Edition::Edition2015, &None);
//! let md = Markdown {
//! content: s,
//! links: &[],
//! ids: &mut id_map,
//! error_codes: ErrorCodes::Yes,
//! edition: Edition::Edition2015,
//! playground: &None,
//! heading_offset: HeadingOffset::H2,
//! };
//! let html = md.into_string();
//! // ... something using html
//! ```
@ -47,6 +55,8 @@ use pulldown_cmark::{
#[cfg(test)]
mod tests;
const MAX_HEADER_LEVEL: u32 = 6;
/// Options for rendering Markdown in the main body of documentation.
pub(crate) fn main_body_opts() -> Options {
Options::ENABLE_TABLES
@ -65,20 +75,33 @@ pub(crate) fn summary_opts() -> Options {
| Options::ENABLE_SMART_PUNCTUATION
}
#[derive(Debug, Clone, Copy)]
pub enum HeadingOffset {
H1 = 0,
H2,
H3,
H4,
H5,
H6,
}
/// When `to_string` is called, this struct will emit the HTML corresponding to
/// the rendered version of the contained markdown string.
pub struct Markdown<'a>(
pub &'a str,
pub struct Markdown<'a> {
pub content: &'a str,
/// A list of link replacements.
pub &'a [RenderedLink],
pub links: &'a [RenderedLink],
/// The current list of used header IDs.
pub &'a mut IdMap,
pub ids: &'a mut IdMap,
/// Whether to allow the use of explicit error codes in doctest lang strings.
pub ErrorCodes,
pub error_codes: ErrorCodes,
/// Default edition to use when parsing doctests (to add a `fn main`).
pub Edition,
pub &'a Option<Playground>,
);
pub edition: Edition,
pub playground: &'a Option<Playground>,
/// Offset at which we render headings.
/// E.g. if `heading_offset: HeadingOffset::H2`, then `# something` renders an `<h2>`.
pub heading_offset: HeadingOffset,
}
/// A tuple struct like `Markdown` that renders the markdown with a table of contents.
crate struct MarkdownWithToc<'a>(
crate &'a str,
@ -489,11 +512,17 @@ struct HeadingLinks<'a, 'b, 'ids, I> {
toc: Option<&'b mut TocBuilder>,
buf: VecDeque<SpannedEvent<'a>>,
id_map: &'ids mut IdMap,
heading_offset: HeadingOffset,
}
impl<'a, 'b, 'ids, I> HeadingLinks<'a, 'b, 'ids, I> {
fn new(iter: I, toc: Option<&'b mut TocBuilder>, ids: &'ids mut IdMap) -> Self {
HeadingLinks { inner: iter, toc, buf: VecDeque::new(), id_map: ids }
fn new(
iter: I,
toc: Option<&'b mut TocBuilder>,
ids: &'ids mut IdMap,
heading_offset: HeadingOffset,
) -> Self {
HeadingLinks { inner: iter, toc, buf: VecDeque::new(), id_map: ids, heading_offset }
}
}
@ -530,6 +559,7 @@ impl<'a, 'b, 'ids, I: Iterator<Item = SpannedEvent<'a>>> Iterator
self.buf.push_front((Event::Html(format!("{} ", sec).into()), 0..0));
}
let level = std::cmp::min(level + (self.heading_offset as u32), MAX_HEADER_LEVEL);
self.buf.push_back((Event::Html(format!("</a></h{}>", level).into()), 0..0));
let start_tags = format!(
@ -1005,7 +1035,15 @@ impl LangString {
impl Markdown<'_> {
pub fn into_string(self) -> String {
let Markdown(md, links, mut ids, codes, edition, playground) = self;
let Markdown {
content: md,
links,
mut ids,
error_codes: codes,
edition,
playground,
heading_offset,
} = self;
// This is actually common enough to special-case
if md.is_empty() {
@ -1026,7 +1064,7 @@ impl Markdown<'_> {
let mut s = String::with_capacity(md.len() * 3 / 2);
let p = HeadingLinks::new(p, None, &mut ids);
let p = HeadingLinks::new(p, None, &mut ids, heading_offset);
let p = Footnotes::new(p);
let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
let p = TableWrapper::new(p);
@ -1048,7 +1086,7 @@ impl MarkdownWithToc<'_> {
let mut toc = TocBuilder::new();
{
let p = HeadingLinks::new(p, Some(&mut toc), &mut ids);
let p = HeadingLinks::new(p, Some(&mut toc), &mut ids, HeadingOffset::H1);
let p = Footnotes::new(p);
let p = TableWrapper::new(p.map(|(ev, _)| ev));
let p = CodeBlocks::new(p, codes, edition, playground);
@ -1077,7 +1115,7 @@ impl MarkdownHtml<'_> {
let mut s = String::with_capacity(md.len() * 3 / 2);
let p = HeadingLinks::new(p, None, &mut ids);
let p = HeadingLinks::new(p, None, &mut ids, HeadingOffset::H1);
let p = Footnotes::new(p);
let p = TableWrapper::new(p.map(|(ev, _)| ev));
let p = CodeBlocks::new(p, codes, edition, playground);
@ -1295,7 +1333,7 @@ crate fn markdown_links(md: &str) -> Vec<MarkdownLink> {
// There's no need to thread an IdMap through to here because
// the IDs generated aren't going to be emitted anywhere.
let mut ids = IdMap::new();
let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids));
let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids, HeadingOffset::H1));
for ev in iter {
if let Event::Start(Tag::Link(kind, dest, _)) = ev.0 {

View File

@ -1,5 +1,5 @@
use super::{find_testable_code, plain_text_summary, short_markdown_summary};
use super::{ErrorCodes, IdMap, Ignore, LangString, Markdown, MarkdownHtml};
use super::{ErrorCodes, HeadingOffset, IdMap, Ignore, LangString, Markdown, MarkdownHtml};
use rustc_span::edition::{Edition, DEFAULT_EDITION};
#[test]
@ -147,33 +147,41 @@ fn test_lang_string_tokenizer() {
fn test_header() {
fn t(input: &str, expect: &str) {
let mut map = IdMap::new();
let output =
Markdown(input, &[], &mut map, ErrorCodes::Yes, DEFAULT_EDITION, &None).into_string();
let output = Markdown {
content: input,
links: &[],
ids: &mut map,
error_codes: ErrorCodes::Yes,
edition: DEFAULT_EDITION,
playground: &None,
heading_offset: HeadingOffset::H2,
}
.into_string();
assert_eq!(output, expect, "original: {}", input);
}
t(
"# Foo bar",
"<h1 id=\"foo-bar\" class=\"section-header\"><a href=\"#foo-bar\">Foo bar</a></h1>",
"<h2 id=\"foo-bar\" class=\"section-header\"><a href=\"#foo-bar\">Foo bar</a></h2>",
);
t(
"## Foo-bar_baz qux",
"<h2 id=\"foo-bar_baz-qux\" class=\"section-header\">\
<a href=\"#foo-bar_baz-qux\">Foo-bar_baz qux</a></h2>",
"<h3 id=\"foo-bar_baz-qux\" class=\"section-header\">\
<a href=\"#foo-bar_baz-qux\">Foo-bar_baz qux</a></h3>",
);
t(
"### **Foo** *bar* baz!?!& -_qux_-%",
"<h3 id=\"foo-bar-baz--qux-\" class=\"section-header\">\
"<h4 id=\"foo-bar-baz--qux-\" class=\"section-header\">\
<a href=\"#foo-bar-baz--qux-\"><strong>Foo</strong> \
<em>bar</em> baz!?!&amp; -<em>qux</em>-%</a>\
</h3>",
</h4>",
);
t(
"#### **Foo?** & \\*bar?!* _`baz`_ ❤ #qux",
"<h4 id=\"foo--bar--baz--qux\" class=\"section-header\">\
"<h5 id=\"foo--bar--baz--qux\" class=\"section-header\">\
<a href=\"#foo--bar--baz--qux\"><strong>Foo?</strong> &amp; *bar?!* \
<em><code>baz</code></em> #qux</a>\
</h4>",
</h5>",
);
}
@ -181,40 +189,48 @@ fn test_header() {
fn test_header_ids_multiple_blocks() {
let mut map = IdMap::new();
fn t(map: &mut IdMap, input: &str, expect: &str) {
let output =
Markdown(input, &[], map, ErrorCodes::Yes, DEFAULT_EDITION, &None).into_string();
let output = Markdown {
content: input,
links: &[],
ids: map,
error_codes: ErrorCodes::Yes,
edition: DEFAULT_EDITION,
playground: &None,
heading_offset: HeadingOffset::H2,
}
.into_string();
assert_eq!(output, expect, "original: {}", input);
}
t(
&mut map,
"# Example",
"<h1 id=\"example\" class=\"section-header\"><a href=\"#example\">Example</a></h1>",
"<h2 id=\"example\" class=\"section-header\"><a href=\"#example\">Example</a></h2>",
);
t(
&mut map,
"# Panics",
"<h1 id=\"panics\" class=\"section-header\"><a href=\"#panics\">Panics</a></h1>",
"<h2 id=\"panics\" class=\"section-header\"><a href=\"#panics\">Panics</a></h2>",
);
t(
&mut map,
"# Example",
"<h1 id=\"example-1\" class=\"section-header\"><a href=\"#example-1\">Example</a></h1>",
"<h2 id=\"example-1\" class=\"section-header\"><a href=\"#example-1\">Example</a></h2>",
);
t(
&mut map,
"# Main",
"<h1 id=\"main-1\" class=\"section-header\"><a href=\"#main-1\">Main</a></h1>",
"<h2 id=\"main-1\" class=\"section-header\"><a href=\"#main-1\">Main</a></h2>",
);
t(
&mut map,
"# Example",
"<h1 id=\"example-2\" class=\"section-header\"><a href=\"#example-2\">Example</a></h1>",
"<h2 id=\"example-2\" class=\"section-header\"><a href=\"#example-2\">Example</a></h2>",
);
t(
&mut map,
"# Panics",
"<h1 id=\"panics-1\" class=\"section-header\"><a href=\"#panics-1\">Panics</a></h1>",
"<h2 id=\"panics-1\" class=\"section-header\"><a href=\"#panics-1\">Panics</a></h2>",
);
}

View File

@ -67,7 +67,7 @@ use crate::html::format::{
href, print_abi_with_space, print_constness_with_space, print_default_space,
print_generic_bounds, print_where_clause, Buffer, HrefError, PrintWithSpace,
};
use crate::html::markdown::{Markdown, MarkdownHtml, MarkdownSummaryLine};
use crate::html::markdown::{HeadingOffset, Markdown, MarkdownHtml, MarkdownSummaryLine};
/// A pair of name and its optional document.
crate type NameDoc = (String, Option<String>);
@ -470,32 +470,45 @@ fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result<Strin
))
}
fn document(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, parent: Option<&clean::Item>) {
fn document(
w: &mut Buffer,
cx: &Context<'_>,
item: &clean::Item,
parent: Option<&clean::Item>,
heading_offset: HeadingOffset,
) {
if let Some(ref name) = item.name {
info!("Documenting {}", name);
}
document_item_info(w, cx, item, parent);
if parent.is_none() {
document_full_collapsible(w, item, cx);
document_full_collapsible(w, item, cx, heading_offset);
} else {
document_full(w, item, cx);
document_full(w, item, cx, heading_offset);
}
}
/// Render md_text as markdown.
fn render_markdown(w: &mut Buffer, cx: &Context<'_>, md_text: &str, links: Vec<RenderedLink>) {
fn render_markdown(
w: &mut Buffer,
cx: &Context<'_>,
md_text: &str,
links: Vec<RenderedLink>,
heading_offset: HeadingOffset,
) {
let mut ids = cx.id_map.borrow_mut();
write!(
w,
"<div class=\"docblock\">{}</div>",
Markdown(
md_text,
&links,
&mut ids,
cx.shared.codes,
cx.shared.edition(),
&cx.shared.playground
)
Markdown {
content: md_text,
links: &links,
ids: &mut ids,
error_codes: cx.shared.codes,
edition: cx.shared.edition(),
playground: &cx.shared.playground,
heading_offset,
}
.into_string()
)
}
@ -531,15 +544,31 @@ fn document_short(
}
}
fn document_full_collapsible(w: &mut Buffer, item: &clean::Item, cx: &Context<'_>) {
document_full_inner(w, item, cx, true);
fn document_full_collapsible(
w: &mut Buffer,
item: &clean::Item,
cx: &Context<'_>,
heading_offset: HeadingOffset,
) {
document_full_inner(w, item, cx, true, heading_offset);
}
fn document_full(w: &mut Buffer, item: &clean::Item, cx: &Context<'_>) {
document_full_inner(w, item, cx, false);
fn document_full(
w: &mut Buffer,
item: &clean::Item,
cx: &Context<'_>,
heading_offset: HeadingOffset,
) {
document_full_inner(w, item, cx, false, heading_offset);
}
fn document_full_inner(w: &mut Buffer, item: &clean::Item, cx: &Context<'_>, is_collapsible: bool) {
fn document_full_inner(
w: &mut Buffer,
item: &clean::Item,
cx: &Context<'_>,
is_collapsible: bool,
heading_offset: HeadingOffset,
) {
if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) {
debug!("Doc block: =====\n{}\n=====", s);
if is_collapsible {
@ -549,10 +578,10 @@ fn document_full_inner(w: &mut Buffer, item: &clean::Item, cx: &Context<'_>, is_
<span>Expand description</span>\
</summary>",
);
render_markdown(w, cx, &s, item.links(cx));
render_markdown(w, cx, &s, item.links(cx), heading_offset);
w.write_str("</details>");
} else {
render_markdown(w, cx, &s, item.links(cx));
render_markdown(w, cx, &s, item.links(cx), heading_offset);
}
}
}
@ -1321,7 +1350,7 @@ fn render_impl(
// because impls can't have a stability.
if item.doc_value().is_some() {
document_item_info(&mut info_buffer, cx, it, Some(parent));
document_full(&mut doc_buffer, item, cx);
document_full(&mut doc_buffer, item, cx, HeadingOffset::H5);
short_documented = false;
} else {
// In case the item isn't documented,
@ -1339,7 +1368,7 @@ fn render_impl(
} else {
document_item_info(&mut info_buffer, cx, item, Some(parent));
if rendering_params.show_def_docs {
document_full(&mut doc_buffer, item, cx);
document_full(&mut doc_buffer, item, cx, HeadingOffset::H5);
short_documented = false;
}
}
@ -1573,14 +1602,15 @@ fn render_impl(
write!(
w,
"<div class=\"docblock\">{}</div>",
Markdown(
&*dox,
&i.impl_item.links(cx),
&mut ids,
cx.shared.codes,
cx.shared.edition(),
&cx.shared.playground
)
Markdown {
content: &*dox,
links: &i.impl_item.links(cx),
ids: &mut ids,
error_codes: cx.shared.codes,
edition: cx.shared.edition(),
playground: &cx.shared.playground,
heading_offset: HeadingOffset::H2
}
.into_string()
);
}

View File

@ -30,7 +30,7 @@ use crate::html::format::{
};
use crate::html::highlight;
use crate::html::layout::Page;
use crate::html::markdown::MarkdownSummaryLine;
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
const ITEM_TABLE_OPEN: &'static str = "<div class=\"item-table\">";
const ITEM_TABLE_CLOSE: &'static str = "</div>";
@ -175,7 +175,7 @@ fn toggle_close(w: &mut Buffer) {
}
fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) {
document(w, cx, item, None);
document(w, cx, item, None, HeadingOffset::H2);
let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::<Vec<usize>>();
@ -482,7 +482,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
notable_traits = notable_traits_decl(&f.decl, cx),
);
});
document(w, cx, it, None)
document(w, cx, it, None, HeadingOffset::H2)
}
fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) {
@ -605,7 +605,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
});
// Trait documentation
document(w, cx, it, None);
document(w, cx, it, None, HeadingOffset::H2);
fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_content: &str) {
write!(
@ -623,7 +623,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
let item_type = m.type_();
let id = cx.derive_id(format!("{}.{}", item_type, name));
let mut content = Buffer::empty_from(w);
document(&mut content, cx, m, Some(t));
document(&mut content, cx, m, Some(t), HeadingOffset::H5);
let toggled = !content.is_empty();
if toggled {
write!(w, "<details class=\"rustdoc-toggle\" open><summary>");
@ -837,7 +837,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
);
});
document(w, cx, it, None);
document(w, cx, it, None, HeadingOffset::H2);
// Render any items associated directly to this alias, as otherwise they
// won't be visible anywhere in the docs. It would be nice to also show
@ -859,7 +859,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
);
});
document(w, cx, it, None);
document(w, cx, it, None, HeadingOffset::H2);
// Render any items associated directly to this alias, as otherwise they
// won't be visible anywhere in the docs. It would be nice to also show
@ -890,7 +890,7 @@ fn item_typedef(
);
});
document(w, cx, it, None);
document(w, cx, it, None, HeadingOffset::H2);
let def_id = it.def_id.expect_def_id();
// Render any items associated directly to this alias, as otherwise they
@ -908,7 +908,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
});
});
document(w, cx, it, None);
document(w, cx, it, None, HeadingOffset::H2);
let mut fields = s
.fields
@ -941,7 +941,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
if let Some(stability_class) = field.stability_class(cx.tcx()) {
write!(w, "<span class=\"stab {stab}\"></span>", stab = stability_class);
}
document(w, cx, field, Some(it));
document(w, cx, field, Some(it), HeadingOffset::H2);
}
}
let def_id = it.def_id.expect_def_id();
@ -1023,7 +1023,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
});
});
document(w, cx, it, None);
document(w, cx, it, None, HeadingOffset::H2);
if !e.variants.is_empty() {
write!(
@ -1052,7 +1052,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));
document(w, cx, variant, Some(it), HeadingOffset::H2);
document_non_exhaustive(w, variant);
use crate::clean::Variant;
@ -1092,7 +1092,7 @@ 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));
document(w, cx, field, Some(variant), HeadingOffset::H2);
}
_ => unreachable!(),
}
@ -1119,7 +1119,7 @@ fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Mac
None,
);
});
document(w, cx, it, None)
document(w, cx, it, None, HeadingOffset::H2)
}
fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean::ProcMacro) {
@ -1149,11 +1149,11 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean
});
}
}
document(w, cx, it, None)
document(w, cx, it, None, HeadingOffset::H2)
}
fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
document(w, cx, it, None);
document(w, cx, it, None, HeadingOffset::H2);
render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
}
@ -1192,7 +1192,7 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::
}
});
document(w, cx, it, None)
document(w, cx, it, None, HeadingOffset::H2)
}
fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) {
@ -1203,7 +1203,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
});
});
document(w, cx, it, None);
document(w, cx, it, None, HeadingOffset::H2);
let mut fields = s
.fields
@ -1239,7 +1239,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
name = field_name,
ty = ty.print(cx)
);
document(w, cx, field, Some(it));
document(w, cx, field, Some(it), HeadingOffset::H2);
}
}
}
@ -1260,7 +1260,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
typ = s.type_.print(cx)
);
});
document(w, cx, it, None)
document(w, cx, it, None, HeadingOffset::H2)
}
fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
@ -1275,13 +1275,13 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
);
});
document(w, cx, it, None);
document(w, cx, it, None, HeadingOffset::H2);
render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
}
fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
document(w, cx, it, None)
document(w, cx, it, None, HeadingOffset::H2)
}
/// Compare two strings treating multi-digit numbers as single units (i.e. natural sort order).

View File

@ -126,7 +126,7 @@ h2 {
h3 {
font-size: 1.3em;
}
h1, h2, h3, h4 {
h1, h2, h3, h4, h5, h6 {
font-weight: 500;
margin: 20px 0 15px 0;
padding-bottom: 6px;
@ -179,7 +179,7 @@ div.impl-items > div {
padding-left: 0;
}
h1, h2, h3, h4,
h1, h2, h3, h4, h5, h6,
.sidebar, a.source, .search-input, .search-results .result-name,
.content table td:first-child > a,
.item-left > a,
@ -501,21 +501,20 @@ nav.sub {
white-space: pre-wrap;
}
.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5, .docblock h6 {
border-bottom: 1px solid;
}
.top-doc .docblock h1 { font-size: 1.3em; }
.top-doc .docblock h2 { font-size: 1.15em; }
.top-doc .docblock h3,
.top-doc .docblock h2 { font-size: 1.3em; }
.top-doc .docblock h3 { font-size: 1.15em; }
.top-doc .docblock h4,
.top-doc .docblock h5 {
.top-doc .docblock h5,
.top-doc .docblock h6 {
font-size: 1em;
}
.docblock h1 { font-size: 1em; }
.docblock h2 { font-size: 0.95em; }
.docblock h3, .docblock h4, .docblock h5 { font-size: 0.9em; }
.docblock h5 { font-size: 1em; }
.docblock h6 { font-size: 0.95em; }
.docblock {
margin-left: 24px;

View File

@ -136,7 +136,7 @@ pre, .rustdoc.source .example-wrap {
border-right: 1px solid #ffb44c;
}
.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5, .docblock h6 {
border-bottom-color: #5c6773;
}

View File

@ -93,7 +93,7 @@ pre, .rustdoc.source .example-wrap {
background-color: #0a042f !important;
}
.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5, .docblock h6 {
border-bottom-color: #DDD;
}

View File

@ -93,7 +93,7 @@ pre, .rustdoc.source .example-wrap {
background-color: #f6fdb0 !important;
}
.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5, .docblock h6 {
border-bottom-color: #ddd;
}

View File

@ -10,7 +10,9 @@ use crate::config::{Options, RenderOptions};
use crate::doctest::{Collector, TestOptions};
use crate::html::escape::Escape;
use crate::html::markdown;
use crate::html::markdown::{find_testable_code, ErrorCodes, IdMap, Markdown, MarkdownWithToc};
use crate::html::markdown::{
find_testable_code, ErrorCodes, HeadingOffset, IdMap, Markdown, MarkdownWithToc,
};
/// Separate any lines at the start of the file that begin with `# ` or `%`.
fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
@ -70,7 +72,16 @@ crate fn render<P: AsRef<Path>>(
let text = if !options.markdown_no_toc {
MarkdownWithToc(text, &mut ids, error_codes, edition, &playground).into_string()
} else {
Markdown(text, &[], &mut ids, error_codes, edition, &playground).into_string()
Markdown {
content: text,
links: &[],
ids: &mut ids,
error_codes,
edition,
playground: &playground,
heading_offset: HeadingOffset::H1,
}
.into_string()
};
let err = write!(

View File

@ -1,4 +1,5 @@
//
// no-system-llvm
// min-llvm-version: 10.0.1
// compile-flags: -O
#![crate_type="lib"]

View File

@ -6,5 +6,5 @@
extern crate external_cross;
// @has host/struct.NeedMoreDocs.html
// @has - '//h1' 'Cross-crate imported docs'
// @has - '//h2' 'Cross-crate imported docs'
pub use external_cross::NeedMoreDocs;

View File

@ -1,6 +1,6 @@
// @has external_doc/struct.IncludeStrDocs.html
// @has - '//h1' 'External Docs'
// @has - '//h2' 'Inline Docs'
// @has - '//h2' 'External Docs'
// @has - '//h3' 'Inline Docs'
#[doc = include_str!("auxiliary/external-doc.md")]
/// ## Inline Docs
pub struct IncludeStrDocs;
@ -8,7 +8,7 @@ pub struct IncludeStrDocs;
macro_rules! dir { () => { "auxiliary" } }
// @has external_doc/struct.EagerExpansion.html
// @has - '//h1' 'External Docs'
// @has - '//h2' 'External Docs'
#[doc = include_str!(concat!(dir!(), "/external-doc.md"))]
/// ## Inline Docs
pub struct EagerExpansion;

View File

@ -1,5 +1,5 @@
// @has issue_42760/struct.NonGen.html
// @has - '//h1' 'Example'
// @has - '//h2' 'Example'
/// Item docs.
///

View File

@ -0,0 +1,29 @@
#![crate_name = "foo"]
// @has foo/trait.Read.html
// @has - '//h2' 'Trait examples'
/// # Trait examples
pub trait Read {
// @has - '//h5' 'Function examples'
/// # Function examples
fn read(&mut self, buf: &mut [u8]) -> Result<usize, ()>;
}
pub struct Foo;
// @has foo/struct.Foo.html
impl Foo {
// @has - '//h5' 'Implementation header'
/// # Implementation header
pub fn bar(&self) -> usize {
1
}
}
impl Read for Foo {
// @has - '//h5' 'Trait implementation header'
/// # Trait implementation header
fn read(&mut self, buf: &mut [u8]) -> Result<usize, ()> {
Ok(1)
}
}

View File

@ -2,7 +2,7 @@
// @has foo/index.html '//*[@class="item-right docblock-short"]/p' 'fooo'
// @!has foo/index.html '//*[@class="item-right docblock-short"]/p/h1' 'fooo'
// @has foo/fn.foo.html '//h1[@id="fooo"]/a[@href="#fooo"]' 'fooo'
// @has foo/fn.foo.html '//h2[@id="fooo"]/a[@href="#fooo"]' 'fooo'
/// # fooo
///
@ -11,7 +11,7 @@ pub fn foo() {}
// @has foo/index.html '//*[@class="item-right docblock-short"]/p' 'mooood'
// @!has foo/index.html '//*[@class="item-right docblock-short"]/p/h2' 'mooood'
// @has foo/foo/index.html '//h2[@id="mooood"]/a[@href="#mooood"]' 'mooood'
// @has foo/foo/index.html '//h3[@id="mooood"]/a[@href="#mooood"]' 'mooood'
/// ## mooood
///

View File

@ -21,7 +21,7 @@
//! ```
// @has "foo/index.html" "//p" "This is the “start” of the document! Howd you know that “its” the start?"
// @has "foo/index.html" "//h1" "Header with “smart punct”"
// @has "foo/index.html" "//h2" "Header with “smart punct”"
// @has "foo/index.html" '//a[@href="https://www.rust-lang.org"]' "link with “smart punct yessiree!"
// @has "foo/index.html" '//code' "this inline code -- it shouldn't have \"smart punct\""
// @has "foo/index.html" '//pre' "let x = \"don't smart-punct me -- please!\";"

View File

@ -20,9 +20,15 @@ error[E0521]: borrowed data escapes outside of associated function
--> $DIR/issue-62097.rs:13:9
|
LL | pub async fn run_dummy_fn(&self) {
| ----- `self` is a reference that is only valid in the associated function body
| -----
| |
| `self` is a reference that is only valid in the associated function body
| let's call the lifetime of this reference `'1`
LL | foo(|| self.bar()).await;
| ^^^^^^^^^^^^^^^^^^ `self` escapes the associated function body here
| ^^^^^^^^^^^^^^^^^^
| |
| `self` escapes the associated function body here
| argument requires that `'1` must outlive `'static`
error: aborting due to 2 previous errors

View File

@ -0,0 +1,10 @@
// Regression test for issue #89497.
// run-rustfix
fn main() {
let pointer: usize = &1_i32 as *const i32 as usize;
let _reference: &'static i32 = unsafe { &*(pointer as *const i32) };
//~^ ERROR: non-primitive cast
//~| HELP: consider borrowing the value
}

View File

@ -0,0 +1,10 @@
// Regression test for issue #89497.
// run-rustfix
fn main() {
let pointer: usize = &1_i32 as *const i32 as usize;
let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 };
//~^ ERROR: non-primitive cast
//~| HELP: consider borrowing the value
}

View File

@ -0,0 +1,15 @@
error[E0605]: non-primitive cast: `*const i32` as `&'static i32`
--> $DIR/issue-89497.rs:7:45
|
LL | let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
|
help: consider borrowing the value
|
LL - let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 };
LL + let _reference: &'static i32 = unsafe { &*(pointer as *const i32) };
|
error: aborting due to previous error
For more information about this error, try `rustc --explain E0605`.

View File

@ -0,0 +1,29 @@
// run-pass
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
trait Foo<const N: usize> {
type Assoc: Default;
}
impl Foo<0> for () {
type Assoc = u32;
}
impl Foo<3> for () {
type Assoc = i64;
}
fn foo<T, const N: usize>(_: T) -> <() as Foo<{ N + 1 }>>::Assoc
where
(): Foo<{ N + 1 }>,
{
Default::default()
}
fn main() {
// Test that we can correctly infer `T` which requires evaluating
// `{ N + 1 }` which has substs containing an inference var
let mut _q = Default::default();
_q = foo::<_, 2>(_q);
}

View File

@ -12,8 +12,9 @@ LL | v as &u8;
|
help: consider borrowing the value
|
LL | &*v as &u8;
| ++
LL - v as &u8;
LL + &*v;
|
error: aborting due to 2 previous errors

View File

@ -2,9 +2,14 @@ error[E0521]: borrowed data escapes outside of function
--> $DIR/dyn-trait.rs:20:5
|
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
| - `x` is a reference that is only valid in the function body
| -- - `x` is a reference that is only valid in the function body
| |
| lifetime `'a` defined here
LL | static_val(x);
| ^^^^^^^^^^^^^ `x` escapes the function body here
| ^^^^^^^^^^^^^
| |
| `x` escapes the function body here
| argument requires that `'a` must outlive `'static`
error: aborting due to previous error

View File

@ -1,10 +1,19 @@
error[E0521]: borrowed data escapes outside of associated function
--> $DIR/issue-16683.rs:4:9
|
LL | trait T<'a> {
| -- lifetime `'a` defined here
LL | fn a(&'a self) -> &'a bool;
LL | fn b(&self) {
| ----- `self` is a reference that is only valid in the associated function body
| -----
| |
| `self` is a reference that is only valid in the associated function body
| let's call the lifetime of this reference `'1`
LL | self.a();
| ^^^^^^^^ `self` escapes the associated function body here
| ^^^^^^^^
| |
| `self` escapes the associated function body here
| argument requires that `'1` must outlive `'a`
error: aborting due to previous error

View File

@ -1,10 +1,19 @@
error[E0521]: borrowed data escapes outside of associated function
--> $DIR/issue-17758.rs:7:9
|
LL | trait Foo<'a> {
| -- lifetime `'a` defined here
LL | fn foo(&'a self);
LL | fn bar(&self) {
| ----- `self` is a reference that is only valid in the associated function body
| -----
| |
| `self` is a reference that is only valid in the associated function body
| let's call the lifetime of this reference `'1`
LL | self.foo();
| ^^^^^^^^^^ `self` escapes the associated function body here
| ^^^^^^^^^^
| |
| `self` escapes the associated function body here
| argument requires that `'1` must outlive `'a`
error: aborting due to previous error

View File

@ -6,8 +6,9 @@ LL | let _q: &isize = p as &isize;
|
help: consider borrowing the value
|
LL | let _q: &isize = &*p as &isize;
| ++
LL - let _q: &isize = p as &isize;
LL + let _q: &isize = &*p;
|
error: aborting due to previous error

View File

@ -2,19 +2,29 @@ error[E0521]: borrowed data escapes outside of function
--> $DIR/lifetime-bound-will-change-warning.rs:34:5
|
LL | fn test2<'a>(x: &'a Box<dyn Fn() + 'a>) {
| - `x` is a reference that is only valid in the function body
| -- - `x` is a reference that is only valid in the function body
| |
| lifetime `'a` defined here
LL | // but ref_obj will not, so warn.
LL | ref_obj(x)
| ^^^^^^^^^^ `x` escapes the function body here
| ^^^^^^^^^^
| |
| `x` escapes the function body here
| argument requires that `'a` must outlive `'static`
error[E0521]: borrowed data escapes outside of function
--> $DIR/lifetime-bound-will-change-warning.rs:39:5
|
LL | fn test2cc<'a>(x: &'a Box<dyn Fn() + 'a>) {
| - `x` is a reference that is only valid in the function body
| -- - `x` is a reference that is only valid in the function body
| |
| lifetime `'a` defined here
LL | // same as test2, but cross crate
LL | lib::ref_obj(x)
| ^^^^^^^^^^^^^^^ `x` escapes the function body here
| ^^^^^^^^^^^^^^^
| |
| `x` escapes the function body here
| argument requires that `'a` must outlive `'static`
error: aborting due to 2 previous errors

View File

@ -28,8 +28,9 @@ LL | let _ = v as &u8;
|
help: consider borrowing the value
|
LL | let _ = &*v as &u8;
| ++
LL - let _ = v as &u8;
LL + let _ = &*v;
|
error[E0605]: non-primitive cast: `*const u8` as `E`
--> $DIR/cast-rfc0401.rs:30:13

View File

@ -38,14 +38,19 @@ error[E0521]: borrowed data escapes outside of function
--> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:32:5
|
LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| ------ `cell_a` is a reference that is only valid in the function body
| -- ------ `cell_a` is a reference that is only valid in the function body
| |
| lifetime `'a` defined here
LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
LL | |
LL | |
LL | | // Only works if 'x: 'y:
LL | | demand_y(x, y, x.get())
LL | | });
| |______^ `cell_a` escapes the function body here
| | ^
| | |
| |______`cell_a` escapes the function body here
| argument requires that `'a` must outlive `'static`
error: aborting due to previous error

View File

@ -38,14 +38,19 @@ error[E0521]: borrowed data escapes outside of function
--> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:35:5
|
LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| ------ `cell_a` is a reference that is only valid in the function body
| -- ------ `cell_a` is a reference that is only valid in the function body
| |
| lifetime `'a` defined here
LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
LL | |
LL | |
LL | | // Only works if 'x: 'y:
LL | | demand_y(x, y, x.get())
LL | | });
| |______^ `cell_a` escapes the function body here
| | ^
| | |
| |______`cell_a` escapes the function body here
| argument requires that `'a` must outlive `'static`
error: aborting due to previous error

View File

@ -0,0 +1,26 @@
// Regression test for issue #67007
// Ensures that we show information about the specific regions involved
#![feature(nll)]
// Covariant over 'a, invariant over 'tcx
struct FnCtxt<'a, 'tcx: 'a>(&'a (), *mut &'tcx ());
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn use_it(&self, _: &'tcx ()) {}
}
struct Consumer<'tcx>(&'tcx ());
impl<'tcx> Consumer<'tcx> {
fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) {
let other = self.use_fcx(fcx); //~ ERROR borrowed data
fcx.use_it(other);
}
fn use_fcx<'a>(&self, _: &FnCtxt<'a, 'tcx>) -> &'a () {
&()
}
}
fn main() {}

View File

@ -0,0 +1,21 @@
error[E0521]: borrowed data escapes outside of associated function
--> $DIR/issue-67007-escaping-data.rs:17:21
|
LL | impl<'tcx> Consumer<'tcx> {
| ---- lifetime `'tcx` defined here
LL | fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) {
| -- ----- --- `fcx` is a reference that is only valid in the associated function body
| | |
| | `self` declared here, outside of the associated function body
| lifetime `'a` defined here
LL | let other = self.use_fcx(fcx);
| ^^^^^^^^^^^^^^^^^
| |
| `fcx` escapes the associated function body here
| argument requires that `'a` must outlive `'tcx`
|
= help: consider adding the following bound: `'a: 'tcx`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0521`.

View File

@ -92,13 +92,20 @@ LL | self.x
error[E0521]: borrowed data escapes outside of associated function
--> $DIR/outlives-suggestion-simple.rs:73:9
|
LL | impl<'a> Foo2<'a> {
| -- lifetime `'a` defined here
LL | // should not produce outlives suggestions to name 'self
LL | fn get_bar(&self) -> Bar2 {
| -----
| |
| `self` declared here, outside of the associated function body
| `self` is a reference that is only valid in the associated function body
| let's call the lifetime of this reference `'1`
LL | Bar2::new(&self)
| ^^^^^^^^^^^^^^^^ `self` escapes the associated function body here
| ^^^^^^^^^^^^^^^^
| |
| `self` escapes the associated function body here
| argument requires that `'1` must outlive `'a`
error: aborting due to 9 previous errors

View File

@ -28,9 +28,14 @@ error[E0521]: borrowed data escapes outside of closure
--> $DIR/closure-substs.rs:29:9
|
LL | |x: &i32, b: fn(&'static i32)| {
| - `x` is a reference that is only valid in the closure body
| - - let's call the lifetime of this reference `'1`
| |
| `x` is a reference that is only valid in the closure body
LL | b(x);
| ^^^^ `x` escapes the closure body here
| ^^^^
| |
| `x` escapes the closure body here
| argument requires that `'1` must outlive `'static`
error: aborting due to 4 previous errors

View File

@ -15,9 +15,14 @@ error[E0521]: borrowed data escapes outside of function
--> $DIR/object-lifetime-default-mybox.rs:31:5
|
LL | fn load2<'a>(ss: &MyBox<dyn SomeTrait + 'a>) -> MyBox<dyn SomeTrait + 'a> {
| -- `ss` is a reference that is only valid in the function body
| -- -- `ss` is a reference that is only valid in the function body
| |
| lifetime `'a` defined here
LL | load0(ss)
| ^^^^^^^^^ `ss` escapes the function body here
| ^^^^^^^^^
| |
| `ss` escapes the function body here
| argument requires that `'a` must outlive `'static`
error: aborting due to 2 previous errors

View File

@ -11,5 +11,5 @@
fn start(_: isize, _: *const *const u8) -> isize {
let _x: Option<!> = None;
let _y: Result<u32, !> = Ok(42);
0
let _z: Result<!, !> = loop {};
}

View File

@ -3,3 +3,4 @@ print-type-size variant `Ok`: 4 bytes
print-type-size field `.0`: 4 bytes
print-type-size type: `std::option::Option<!>`: 0 bytes, alignment: 1 bytes
print-type-size variant `None`: 0 bytes
print-type-size type: `std::result::Result<!, !>`: 0 bytes, alignment: 1 bytes

View File

@ -2,8 +2,11 @@ error[E0521]: borrowed data escapes outside of closure
--> $DIR/issue-78262.rs:14:26
|
LL | let f = |x: &dyn TT| x.func();
| - ^^^^^^^^ `x` escapes the closure body here
| |
| - - ^^^^^^^^
| | | |
| | | `x` escapes the closure body here
| | | argument requires that `'1` must outlive `'static`
| | let's call the lifetime of this reference `'1`
| `x` is a reference that is only valid in the closure body
error: aborting due to previous error

View File

@ -2,8 +2,11 @@ error[E0521]: borrowed data escapes outside of closure
--> $DIR/issue-78262.rs:14:26
|
LL | let f = |x: &dyn TT| x.func();
| - ^^^^^^^^ `x` escapes the closure body here
| |
| - - ^^^^^^^^
| | | |
| | | `x` escapes the closure body here
| | | argument requires that `'1` must outlive `'static`
| | let's call the lifetime of this reference `'1`
| `x` is a reference that is only valid in the closure body
error: aborting due to previous error

View File

@ -2,10 +2,15 @@ error[E0521]: borrowed data escapes outside of function
--> $DIR/region-invariant-static-error-reporting.rs:15:9
|
LL | fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
| - `x` is a reference that is only valid in the function body
| -- - `x` is a reference that is only valid in the function body
| |
| lifetime `'a` defined here
LL | let bad = if x.is_some() {
LL | x.unwrap()
| ^^^^^^^^^^ `x` escapes the function body here
| ^^^^^^^^^^
| |
| `x` escapes the function body here
| argument requires that `'a` must outlive `'static`
error: aborting due to previous error

View File

@ -2,12 +2,17 @@ error[E0521]: borrowed data escapes outside of function
--> $DIR/regions-bounded-method-type-parameters-trait-bound.rs:20:5
|
LL | fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
| - - `b` is a reference that is only valid in the function body
| |
| `a` declared here, outside of the function body
| -- -- - - `b` is a reference that is only valid in the function body
| | | |
| | | `a` declared here, outside of the function body
| | lifetime `'b` defined here
| lifetime `'a` defined here
LL | // Here the value provided for 'y is 'b, and hence 'b:'a does not hold.
LL | f.method(b);
| ^^^^^^^^^^^ `b` escapes the function body here
| ^^^^^^^^^^^
| |
| `b` escapes the function body here
| argument requires that `'b` must outlive `'a`
|
= help: consider adding the following bound: `'b: 'a`

View File

@ -2,33 +2,53 @@ error[E0521]: borrowed data escapes outside of function
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:9
|
LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a {
| --- `val` is a reference that is only valid in the function body
| -- --- `val` is a reference that is only valid in the function body
| |
| lifetime `'a` defined here
LL | val.use_self::<T>()
| ^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here
| ^^^^^^^^^^^^^^^^^^^
| |
| `val` escapes the function body here
| argument requires that `'a` must outlive `'static`
error[E0521]: borrowed data escapes outside of function
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:9
|
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
| --- `val` is a reference that is only valid in the function body
| -- --- `val` is a reference that is only valid in the function body
| |
| lifetime `'a` defined here
LL | val.use_self()
| ^^^^^^^^^^^^^^ `val` escapes the function body here
| ^^^^^^^^^^^^^^
| |
| `val` escapes the function body here
| argument requires that `'a` must outlive `'static`
error[E0521]: borrowed data escapes outside of function
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:88:9
|
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
| --- `val` is a reference that is only valid in the function body
| -- --- `val` is a reference that is only valid in the function body
| |
| lifetime `'a` defined here
LL | val.use_self()
| ^^^^^^^^^^^^^^ `val` escapes the function body here
| ^^^^^^^^^^^^^^
| |
| `val` escapes the function body here
| argument requires that `'a` must outlive `'static`
error[E0521]: borrowed data escapes outside of function
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:9
|
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
| --- `val` is a reference that is only valid in the function body
| -- --- `val` is a reference that is only valid in the function body
| |
| lifetime `'a` defined here
LL | MyTrait::use_self(val)
| ^^^^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here
| ^^^^^^^^^^^^^^^^^^^^^^
| |
| `val` escapes the function body here
| argument requires that `'a` must outlive `'static`
error: aborting due to 4 previous errors

View File

@ -14,7 +14,7 @@ use std::path::PathBuf;
use rustc_span::edition::DEFAULT_EDITION;
use rustdoc::html::markdown::{ErrorCodes, IdMap, Markdown, Playground};
use rustdoc::html::markdown::{ErrorCodes, HeadingOffset, IdMap, Markdown, Playground};
pub struct ErrorMetadata {
pub description: Option<String>,
@ -119,14 +119,15 @@ impl Formatter for HTMLFormatter {
write!(
output,
"{}",
Markdown(
desc,
&[],
&mut id_map,
ErrorCodes::Yes,
DEFAULT_EDITION,
&Some(playground)
)
Markdown {
content: desc,
links: &[],
ids: &mut id_map,
error_codes: ErrorCodes::Yes,
edition: DEFAULT_EDITION,
playground: &Some(playground),
heading_offset: HeadingOffset::H1,
}
.into_string()
)?
}