Auto merge of #82393 - JohnTitor:rollup-5c8jryl, r=JohnTitor
Rollup of 9 pull requests Successful merges: - #82098 (Add internal `collect_into_array[_unchecked]` to remove duplicate code) - #82228 (Provide NonZero_c_* integers) - #82287 (Make "missing field" error message more natural) - #82351 (Use the first paragraph, instead of cookie-cutter text, for rustdoc descriptions) - #82353 (rustdoc: Remove unnecessary `Cell` around `param_env`) - #82367 (remove redundant option/result wrapping of return values) - #82372 (improve UnsafeCell docs) - #82379 (Fix sizes of repr(C) enums on hexagon) - #82382 (rustdoc: Remove `fake_def_ids` RefCell) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
8a9f7862bc
@ -1035,14 +1035,14 @@ pub fn find_transparency(
|
||||
pub fn allow_internal_unstable<'a>(
|
||||
sess: &'a Session,
|
||||
attrs: &'a [Attribute],
|
||||
) -> Option<impl Iterator<Item = Symbol> + 'a> {
|
||||
) -> impl Iterator<Item = Symbol> + 'a {
|
||||
allow_unstable(sess, attrs, sym::allow_internal_unstable)
|
||||
}
|
||||
|
||||
pub fn rustc_allow_const_fn_unstable<'a>(
|
||||
sess: &'a Session,
|
||||
attrs: &'a [Attribute],
|
||||
) -> Option<impl Iterator<Item = Symbol> + 'a> {
|
||||
) -> impl Iterator<Item = Symbol> + 'a {
|
||||
allow_unstable(sess, attrs, sym::rustc_allow_const_fn_unstable)
|
||||
}
|
||||
|
||||
@ -1050,7 +1050,7 @@ fn allow_unstable<'a>(
|
||||
sess: &'a Session,
|
||||
attrs: &'a [Attribute],
|
||||
symbol: Symbol,
|
||||
) -> Option<impl Iterator<Item = Symbol> + 'a> {
|
||||
) -> impl Iterator<Item = Symbol> + 'a {
|
||||
let attrs = sess.filter_by_name(attrs, symbol);
|
||||
let list = attrs
|
||||
.filter_map(move |attr| {
|
||||
@ -1064,7 +1064,7 @@ fn allow_unstable<'a>(
|
||||
})
|
||||
.flatten();
|
||||
|
||||
Some(list.into_iter().filter_map(move |it| {
|
||||
list.into_iter().filter_map(move |it| {
|
||||
let name = it.ident().map(|ident| ident.name);
|
||||
if name.is_none() {
|
||||
sess.diagnostic().span_err(
|
||||
@ -1073,5 +1073,5 @@ fn allow_unstable<'a>(
|
||||
);
|
||||
}
|
||||
name
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
@ -735,7 +735,7 @@ fn execute_work_item<B: ExtraBackendMethods>(
|
||||
match work_item {
|
||||
WorkItem::Optimize(module) => execute_optimize_work_item(cgcx, module, module_config),
|
||||
WorkItem::CopyPostLtoArtifacts(module) => {
|
||||
execute_copy_from_cache_work_item(cgcx, module, module_config)
|
||||
Ok(execute_copy_from_cache_work_item(cgcx, module, module_config))
|
||||
}
|
||||
WorkItem::LTO(module) => execute_lto_work_item(cgcx, module, module_config),
|
||||
}
|
||||
@ -844,7 +844,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
|
||||
cgcx: &CodegenContext<B>,
|
||||
module: CachedModuleCodegen,
|
||||
module_config: &ModuleConfig,
|
||||
) -> Result<WorkItemResult<B>, FatalError> {
|
||||
) -> WorkItemResult<B> {
|
||||
let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();
|
||||
let mut object = None;
|
||||
if let Some(saved_file) = module.source.saved_file {
|
||||
@ -870,13 +870,13 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
|
||||
|
||||
assert_eq!(object.is_some(), module_config.emit_obj != EmitObj::None);
|
||||
|
||||
Ok(WorkItemResult::Compiled(CompiledModule {
|
||||
WorkItemResult::Compiled(CompiledModule {
|
||||
name: module.name,
|
||||
kind: ModuleKind::Regular,
|
||||
object,
|
||||
dwarf_object: None,
|
||||
bytecode: None,
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
fn execute_lto_work_item<B: ExtraBackendMethods>(
|
||||
|
@ -756,8 +756,8 @@ pub fn new(
|
||||
name: Symbol,
|
||||
attrs: &[ast::Attribute],
|
||||
) -> SyntaxExtension {
|
||||
let allow_internal_unstable = attr::allow_internal_unstable(sess, &attrs)
|
||||
.map(|features| features.collect::<Vec<Symbol>>().into());
|
||||
let allow_internal_unstable =
|
||||
Some(attr::allow_internal_unstable(sess, &attrs).collect::<Vec<Symbol>>().into());
|
||||
|
||||
let mut local_inner_macros = false;
|
||||
if let Some(macro_export) = sess.find_by_name(attrs, sym::macro_export) {
|
||||
|
@ -266,7 +266,7 @@ pub fn get_bytes_mut(
|
||||
let range = self.check_bounds(ptr.offset, size);
|
||||
|
||||
self.mark_init(ptr, size, true);
|
||||
self.clear_relocations(cx, ptr, size)?;
|
||||
self.clear_relocations(cx, ptr, size);
|
||||
|
||||
AllocationExtra::memory_written(self, ptr, size)?;
|
||||
|
||||
@ -484,18 +484,13 @@ fn check_relocations(
|
||||
/// uninitialized. This is a somewhat odd "spooky action at a distance",
|
||||
/// but it allows strictly more code to run than if we would just error
|
||||
/// immediately in that case.
|
||||
fn clear_relocations(
|
||||
&mut self,
|
||||
cx: &impl HasDataLayout,
|
||||
ptr: Pointer<Tag>,
|
||||
size: Size,
|
||||
) -> InterpResult<'tcx> {
|
||||
fn clear_relocations(&mut self, cx: &impl HasDataLayout, ptr: Pointer<Tag>, size: Size) {
|
||||
// Find the start and end of the given range and its outermost relocations.
|
||||
let (first, last) = {
|
||||
// Find all relocations overlapping the given range.
|
||||
let relocations = self.get_relocations(cx, ptr, size);
|
||||
if relocations.is_empty() {
|
||||
return Ok(());
|
||||
return;
|
||||
}
|
||||
|
||||
(
|
||||
@ -517,8 +512,6 @@ fn clear_relocations(
|
||||
|
||||
// Forget all the relocations.
|
||||
self.relocations.remove_range(first..last);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Errors if there are relocations overlapping with the edges of the
|
||||
|
@ -130,6 +130,7 @@ fn repr_discr<'tcx>(
|
||||
|
||||
if repr.c() {
|
||||
match &tcx.sess.target.arch[..] {
|
||||
"hexagon" => min_from_extern = Some(I8),
|
||||
// WARNING: the ARM EABI has two variants; the one corresponding
|
||||
// to `at_least == I32` appears to be used on Linux and NetBSD,
|
||||
// but some systems may use the variant corresponding to no
|
||||
|
@ -23,11 +23,7 @@
|
||||
mod caller_location;
|
||||
mod type_name;
|
||||
|
||||
fn numeric_intrinsic<'tcx, Tag>(
|
||||
name: Symbol,
|
||||
bits: u128,
|
||||
kind: Primitive,
|
||||
) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
fn numeric_intrinsic<Tag>(name: Symbol, bits: u128, kind: Primitive) -> Scalar<Tag> {
|
||||
let size = match kind {
|
||||
Primitive::Int(integer, _) => integer.size(),
|
||||
_ => bug!("invalid `{}` argument: {:?}", name, bits),
|
||||
@ -41,7 +37,7 @@ fn numeric_intrinsic<'tcx, Tag>(
|
||||
sym::bitreverse => (bits << extra).reverse_bits(),
|
||||
_ => bug!("not a numeric intrinsic: {}", name),
|
||||
};
|
||||
Ok(Scalar::from_uint(bits_out, size))
|
||||
Scalar::from_uint(bits_out, size)
|
||||
}
|
||||
|
||||
/// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated
|
||||
@ -208,7 +204,7 @@ pub fn emulate_intrinsic(
|
||||
if nonzero && bits == 0 {
|
||||
throw_ub_format!("`{}_nonzero` called on 0", intrinsic_name);
|
||||
}
|
||||
let out_val = numeric_intrinsic(intrinsic_name, bits, kind)?;
|
||||
let out_val = numeric_intrinsic(intrinsic_name, bits, kind);
|
||||
self.write_scalar(out_val, dest)?;
|
||||
}
|
||||
sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
|
||||
|
@ -85,8 +85,7 @@ pub fn rustc_allow_const_fn_unstable(
|
||||
feature_gate: Symbol,
|
||||
) -> bool {
|
||||
let attrs = tcx.get_attrs(def_id);
|
||||
attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs)
|
||||
.map_or(false, |mut features| features.any(|name| name == feature_gate))
|
||||
attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs).any(|name| name == feature_gate)
|
||||
}
|
||||
|
||||
// Returns `true` if the given `const fn` is "const-stable".
|
||||
|
@ -426,7 +426,7 @@ fn parse_range_expr(
|
||||
let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
|
||||
let limits =
|
||||
if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
|
||||
Ok(self.mk_expr(span, self.mk_range(Some(lhs), rhs, limits)?, AttrVec::new()))
|
||||
Ok(self.mk_expr(span, self.mk_range(Some(lhs), rhs, limits), AttrVec::new()))
|
||||
}
|
||||
|
||||
fn is_at_start_of_range_notation_rhs(&self) -> bool {
|
||||
@ -474,7 +474,7 @@ fn parse_prefix_range_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a,
|
||||
} else {
|
||||
(lo, None)
|
||||
};
|
||||
Ok(this.mk_expr(span, this.mk_range(None, opt_end, limits)?, attrs.into()))
|
||||
Ok(this.mk_expr(span, this.mk_range(None, opt_end, limits), attrs.into()))
|
||||
})
|
||||
}
|
||||
|
||||
@ -1041,7 +1041,7 @@ fn parse_index_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>>
|
||||
/// Assuming we have just parsed `.`, continue parsing into an expression.
|
||||
fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
if self.token.uninterpolated_span().rust_2018() && self.eat_keyword(kw::Await) {
|
||||
return self.mk_await_expr(self_arg, lo);
|
||||
return Ok(self.mk_await_expr(self_arg, lo));
|
||||
}
|
||||
|
||||
let fn_span_lo = self.token.span;
|
||||
@ -2396,12 +2396,12 @@ fn mk_range(
|
||||
start: Option<P<Expr>>,
|
||||
end: Option<P<Expr>>,
|
||||
limits: RangeLimits,
|
||||
) -> PResult<'a, ExprKind> {
|
||||
) -> ExprKind {
|
||||
if end.is_none() && limits == RangeLimits::Closed {
|
||||
self.error_inclusive_range_with_no_end(self.prev_token.span);
|
||||
Ok(ExprKind::Err)
|
||||
ExprKind::Err
|
||||
} else {
|
||||
Ok(ExprKind::Range(start, end, limits))
|
||||
ExprKind::Range(start, end, limits)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2421,11 +2421,11 @@ fn mk_call(&self, f: P<Expr>, args: Vec<P<Expr>>) -> ExprKind {
|
||||
ExprKind::Call(f, args)
|
||||
}
|
||||
|
||||
fn mk_await_expr(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
fn mk_await_expr(&mut self, self_arg: P<Expr>, lo: Span) -> P<Expr> {
|
||||
let span = lo.to(self.prev_token.span);
|
||||
let await_expr = self.mk_expr(span, ExprKind::Await(self_arg), AttrVec::new());
|
||||
self.recover_from_await_method_call();
|
||||
Ok(await_expr)
|
||||
await_expr
|
||||
}
|
||||
|
||||
crate fn mk_expr(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> {
|
||||
|
@ -1679,7 +1679,7 @@ pub(super) fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
|
||||
let constness = self.parse_constness();
|
||||
let asyncness = self.parse_asyncness();
|
||||
let unsafety = self.parse_unsafety();
|
||||
let ext = self.parse_extern()?;
|
||||
let ext = self.parse_extern();
|
||||
|
||||
if let Async::Yes { span, .. } = asyncness {
|
||||
self.ban_async_in_2015(span);
|
||||
|
@ -1202,12 +1202,8 @@ fn recover_incorrect_vis_restriction(&mut self) -> PResult<'a, ()> {
|
||||
}
|
||||
|
||||
/// Parses `extern string_literal?`.
|
||||
fn parse_extern(&mut self) -> PResult<'a, Extern> {
|
||||
Ok(if self.eat_keyword(kw::Extern) {
|
||||
Extern::from_abi(self.parse_abi())
|
||||
} else {
|
||||
Extern::None
|
||||
})
|
||||
fn parse_extern(&mut self) -> Extern {
|
||||
if self.eat_keyword(kw::Extern) { Extern::from_abi(self.parse_abi()) } else { Extern::None }
|
||||
}
|
||||
|
||||
/// Parses a string literal as an ABI spec.
|
||||
|
@ -106,7 +106,7 @@ fn const_check_violated(&self, expr: NonConstExpr, span: Span) {
|
||||
// However, we cannot allow stable `const fn`s to use unstable features without an explicit
|
||||
// opt-in via `rustc_allow_const_fn_unstable`.
|
||||
attr::rustc_allow_const_fn_unstable(&tcx.sess, &tcx.get_attrs(def_id))
|
||||
.map_or(false, |mut features| features.any(|name| name == feature_gate))
|
||||
.any(|name| name == feature_gate)
|
||||
};
|
||||
|
||||
match required_gates {
|
||||
|
@ -1348,7 +1348,6 @@ fn report_missing_fields(
|
||||
span: Span,
|
||||
remaining_fields: FxHashMap<Ident, (usize, &ty::FieldDef)>,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
let len = remaining_fields.len();
|
||||
|
||||
let mut displayable_field_names =
|
||||
@ -1356,25 +1355,29 @@ fn report_missing_fields(
|
||||
|
||||
displayable_field_names.sort();
|
||||
|
||||
let truncated_fields_error = if len <= 3 {
|
||||
String::new()
|
||||
} else {
|
||||
format!(" and {} other field{}", (len - 3), if len - 3 == 1 { "" } else { "s" })
|
||||
let mut truncated_fields_error = String::new();
|
||||
let remaining_fields_names = match &displayable_field_names[..] {
|
||||
[field1] => format!("`{}`", field1),
|
||||
[field1, field2] => format!("`{}` and `{}`", field1, field2),
|
||||
[field1, field2, field3] => format!("`{}`, `{}` and `{}`", field1, field2, field3),
|
||||
_ => {
|
||||
truncated_fields_error =
|
||||
format!(" and {} other field{}", len - 3, pluralize!(len - 3));
|
||||
displayable_field_names
|
||||
.iter()
|
||||
.take(3)
|
||||
.map(|n| format!("`{}`", n))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
}
|
||||
};
|
||||
|
||||
let remaining_fields_names = displayable_field_names
|
||||
.iter()
|
||||
.take(3)
|
||||
.map(|n| format!("`{}`", n))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
self.tcx.sess,
|
||||
span,
|
||||
E0063,
|
||||
"missing field{} {}{} in initializer of `{}`",
|
||||
pluralize!(remaining_fields.len()),
|
||||
pluralize!(len),
|
||||
remaining_fields_names,
|
||||
truncated_fields_error,
|
||||
adt_ty
|
||||
|
@ -11,8 +11,9 @@
|
||||
use crate::convert::{Infallible, TryFrom};
|
||||
use crate::fmt;
|
||||
use crate::hash::{self, Hash};
|
||||
use crate::iter::TrustedLen;
|
||||
use crate::marker::Unsize;
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::mem::{self, MaybeUninit};
|
||||
use crate::ops::{Index, IndexMut};
|
||||
use crate::slice::{Iter, IterMut};
|
||||
|
||||
@ -426,41 +427,13 @@ macro_rules! array_impl_default {
|
||||
/// assert_eq!(y, [6, 9, 3, 3]);
|
||||
/// ```
|
||||
#[unstable(feature = "array_map", issue = "75243")]
|
||||
pub fn map<F, U>(self, mut f: F) -> [U; N]
|
||||
pub fn map<F, U>(self, f: F) -> [U; N]
|
||||
where
|
||||
F: FnMut(T) -> U,
|
||||
{
|
||||
struct Guard<T, const N: usize> {
|
||||
dst: *mut T,
|
||||
initialized: usize,
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Drop for Guard<T, N> {
|
||||
fn drop(&mut self) {
|
||||
debug_assert!(self.initialized <= N);
|
||||
|
||||
let initialized_part =
|
||||
crate::ptr::slice_from_raw_parts_mut(self.dst, self.initialized);
|
||||
// SAFETY: this raw slice will contain only initialized objects
|
||||
// that's why, it is allowed to drop it.
|
||||
unsafe {
|
||||
crate::ptr::drop_in_place(initialized_part);
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut dst = MaybeUninit::uninit_array::<N>();
|
||||
let mut guard: Guard<U, N> =
|
||||
Guard { dst: MaybeUninit::slice_as_mut_ptr(&mut dst), initialized: 0 };
|
||||
for (src, dst) in IntoIter::new(self).zip(&mut dst) {
|
||||
dst.write(f(src));
|
||||
guard.initialized += 1;
|
||||
}
|
||||
// FIXME: Convert to crate::mem::transmute once it works with generics.
|
||||
// unsafe { crate::mem::transmute::<[MaybeUninit<U>; N], [U; N]>(dst) }
|
||||
crate::mem::forget(guard);
|
||||
// SAFETY: At this point we've properly initialized the whole array
|
||||
// and we just need to cast it to the correct type.
|
||||
unsafe { crate::mem::transmute_copy::<_, [U; N]>(&dst) }
|
||||
// SAFETY: we know for certain that this iterator will yield exactly `N`
|
||||
// items.
|
||||
unsafe { collect_into_array_unchecked(&mut IntoIter::new(self).map(f)) }
|
||||
}
|
||||
|
||||
/// 'Zips up' two arrays into a single array of pairs.
|
||||
@ -481,15 +454,11 @@ fn drop(&mut self) {
|
||||
/// ```
|
||||
#[unstable(feature = "array_zip", issue = "80094")]
|
||||
pub fn zip<U>(self, rhs: [U; N]) -> [(T, U); N] {
|
||||
let mut dst = MaybeUninit::uninit_array::<N>();
|
||||
for (i, (lhs, rhs)) in IntoIter::new(self).zip(IntoIter::new(rhs)).enumerate() {
|
||||
dst[i].write((lhs, rhs));
|
||||
}
|
||||
// FIXME: Convert to crate::mem::transmute once it works with generics.
|
||||
// unsafe { crate::mem::transmute::<[MaybeUninit<U>; N], [U; N]>(dst) }
|
||||
// SAFETY: At this point we've properly initialized the whole array
|
||||
// and we just need to cast it to the correct type.
|
||||
unsafe { crate::mem::transmute_copy::<_, [(T, U); N]>(&dst) }
|
||||
let mut iter = IntoIter::new(self).zip(IntoIter::new(rhs));
|
||||
|
||||
// SAFETY: we know for certain that this iterator will yield exactly `N`
|
||||
// items.
|
||||
unsafe { collect_into_array_unchecked(&mut iter) }
|
||||
}
|
||||
|
||||
/// Returns a slice containing the entire array. Equivalent to `&s[..]`.
|
||||
@ -535,16 +504,9 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
|
||||
/// ```
|
||||
#[unstable(feature = "array_methods", issue = "76118")]
|
||||
pub fn each_ref(&self) -> [&T; N] {
|
||||
// Unlike in `map`, we don't need a guard here, as dropping a reference
|
||||
// is a noop.
|
||||
let mut out = MaybeUninit::uninit_array::<N>();
|
||||
for (src, dst) in self.iter().zip(&mut out) {
|
||||
dst.write(src);
|
||||
}
|
||||
|
||||
// SAFETY: All elements of `dst` are properly initialized and
|
||||
// `MaybeUninit<T>` has the same layout as `T`, so this cast is valid.
|
||||
unsafe { (&mut out as *mut _ as *mut [&T; N]).read() }
|
||||
// SAFETY: we know for certain that this iterator will yield exactly `N`
|
||||
// items.
|
||||
unsafe { collect_into_array_unchecked(&mut self.iter()) }
|
||||
}
|
||||
|
||||
/// Borrows each element mutably and returns an array of mutable references
|
||||
@ -564,15 +526,103 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
|
||||
/// ```
|
||||
#[unstable(feature = "array_methods", issue = "76118")]
|
||||
pub fn each_mut(&mut self) -> [&mut T; N] {
|
||||
// Unlike in `map`, we don't need a guard here, as dropping a reference
|
||||
// is a noop.
|
||||
let mut out = MaybeUninit::uninit_array::<N>();
|
||||
for (src, dst) in self.iter_mut().zip(&mut out) {
|
||||
dst.write(src);
|
||||
}
|
||||
|
||||
// SAFETY: All elements of `dst` are properly initialized and
|
||||
// `MaybeUninit<T>` has the same layout as `T`, so this cast is valid.
|
||||
unsafe { (&mut out as *mut _ as *mut [&mut T; N]).read() }
|
||||
// SAFETY: we know for certain that this iterator will yield exactly `N`
|
||||
// items.
|
||||
unsafe { collect_into_array_unchecked(&mut self.iter_mut()) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Pulls `N` items from `iter` and returns them as an array. If the iterator
|
||||
/// yields fewer than `N` items, this function exhibits undefined behavior.
|
||||
///
|
||||
/// See [`collect_into_array`] for more information.
|
||||
///
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee that `iter` yields at least `N` items.
|
||||
/// Violating this condition causes undefined behavior.
|
||||
unsafe fn collect_into_array_unchecked<I, const N: usize>(iter: &mut I) -> [I::Item; N]
|
||||
where
|
||||
// Note: `TrustedLen` here is somewhat of an experiment. This is just an
|
||||
// internal function, so feel free to remove if this bound turns out to be a
|
||||
// bad idea. In that case, remember to also remove the lower bound
|
||||
// `debug_assert!` below!
|
||||
I: Iterator + TrustedLen,
|
||||
{
|
||||
debug_assert!(N <= iter.size_hint().1.unwrap_or(usize::MAX));
|
||||
debug_assert!(N <= iter.size_hint().0);
|
||||
|
||||
match collect_into_array(iter) {
|
||||
Some(array) => array,
|
||||
// SAFETY: covered by the function contract.
|
||||
None => unsafe { crate::hint::unreachable_unchecked() },
|
||||
}
|
||||
}
|
||||
|
||||
/// Pulls `N` items from `iter` and returns them as an array. If the iterator
|
||||
/// yields fewer than `N` items, `None` is returned and all already yielded
|
||||
/// items are dropped.
|
||||
///
|
||||
/// Since the iterator is passed as mutable reference and this function calls
|
||||
/// `next` at most `N` times, the iterator can still be used afterwards to
|
||||
/// retrieve the remaining items.
|
||||
///
|
||||
/// If `iter.next()` panicks, all items already yielded by the iterator are
|
||||
/// dropped.
|
||||
fn collect_into_array<I, const N: usize>(iter: &mut I) -> Option<[I::Item; N]>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
if N == 0 {
|
||||
// SAFETY: An empty array is always inhabited and has no validity invariants.
|
||||
return unsafe { Some(mem::zeroed()) };
|
||||
}
|
||||
|
||||
struct Guard<T, const N: usize> {
|
||||
ptr: *mut T,
|
||||
initialized: usize,
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Drop for Guard<T, N> {
|
||||
fn drop(&mut self) {
|
||||
debug_assert!(self.initialized <= N);
|
||||
|
||||
let initialized_part = crate::ptr::slice_from_raw_parts_mut(self.ptr, self.initialized);
|
||||
|
||||
// SAFETY: this raw slice will contain only initialized objects.
|
||||
unsafe {
|
||||
crate::ptr::drop_in_place(initialized_part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut array = MaybeUninit::uninit_array::<N>();
|
||||
let mut guard: Guard<_, N> =
|
||||
Guard { ptr: MaybeUninit::slice_as_mut_ptr(&mut array), initialized: 0 };
|
||||
|
||||
while let Some(item) = iter.next() {
|
||||
// SAFETY: `guard.initialized` starts at 0, is increased by one in the
|
||||
// loop and the loop is aborted once it reaches N (which is
|
||||
// `array.len()`).
|
||||
unsafe {
|
||||
array.get_unchecked_mut(guard.initialized).write(item);
|
||||
}
|
||||
guard.initialized += 1;
|
||||
|
||||
// Check if the whole array was initialized.
|
||||
if guard.initialized == N {
|
||||
mem::forget(guard);
|
||||
|
||||
// SAFETY: the condition above asserts that all elements are
|
||||
// initialized.
|
||||
let out = unsafe { MaybeUninit::array_assume_init(array) };
|
||||
return Some(out);
|
||||
}
|
||||
}
|
||||
|
||||
// This is only reached if the iterator is exhausted before
|
||||
// `guard.initialized` reaches `N`. Also note that `guard` is dropped here,
|
||||
// dropping all already initialized elements.
|
||||
None
|
||||
}
|
||||
|
@ -1619,17 +1619,18 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
||||
/// The core primitive for interior mutability in Rust.
|
||||
///
|
||||
/// `UnsafeCell<T>` is a type that wraps some `T` and indicates unsafe interior operations on the
|
||||
/// wrapped type. Types with an `UnsafeCell<T>` field are considered to have an 'unsafe interior'.
|
||||
/// The `UnsafeCell<T>` type is the only legal way to obtain aliasable data that is considered
|
||||
/// mutable. In general, transmuting a `&T` type into a `&mut T` is considered undefined behavior.
|
||||
/// If you have a reference `&T`, then normally in Rust the compiler performs optimizations based on
|
||||
/// the knowledge that `&T` points to immutable data. Mutating that data, for example through an
|
||||
/// alias or by transmuting an `&T` into an `&mut T`, is considered undefined behavior.
|
||||
/// `UnsafeCell<T>` opts-out of the immutability guarantee for `&T`: a shared reference
|
||||
/// `&UnsafeCell<T>` may point to data that is being mutated. This is called "interior mutability".
|
||||
///
|
||||
/// If you have a reference `&SomeStruct`, then normally in Rust all fields of `SomeStruct` are
|
||||
/// immutable. The compiler makes optimizations based on the knowledge that `&T` is not mutably
|
||||
/// aliased or mutated, and that `&mut T` is unique. `UnsafeCell<T>` is the only core language
|
||||
/// feature to work around the restriction that `&T` may not be mutated. All other types that
|
||||
/// allow internal mutability, such as `Cell<T>` and `RefCell<T>`, use `UnsafeCell` to wrap their
|
||||
/// internal data. There is *no* legal way to obtain aliasing `&mut`, not even with `UnsafeCell<T>`.
|
||||
/// All other types that allow internal mutability, such as `Cell<T>` and `RefCell<T>`, internally
|
||||
/// use `UnsafeCell` to wrap their data.
|
||||
///
|
||||
/// Note that only the immutability guarantee for shared references is affected by `UnsafeCell`. The
|
||||
/// uniqueness guarantee for mutable references is unaffected. There is *no* legal way to obtain
|
||||
/// aliasing `&mut`, not even with `UnsafeCell<T>`.
|
||||
///
|
||||
/// The `UnsafeCell` API itself is technically very simple: [`.get()`] gives you a raw pointer
|
||||
/// `*mut T` to its contents. It is up to _you_ as the abstraction designer to use that raw pointer
|
||||
|
@ -263,6 +263,7 @@
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(extend_one)]
|
||||
#![feature(extended_key_value_attributes)]
|
||||
#![feature(external_doc)]
|
||||
#![feature(fn_traits)]
|
||||
#![feature(format_args_nl)]
|
||||
|
@ -11,7 +11,41 @@
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[doc(include = "char.md")]
|
||||
use core::num::*;
|
||||
|
||||
macro_rules! type_alias_no_nz {
|
||||
{
|
||||
$Docfile:tt, $Alias:ident = $Real:ty;
|
||||
$( $Cfg:tt )*
|
||||
} => {
|
||||
#[doc(include = $Docfile)]
|
||||
$( $Cfg )*
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type $Alias = $Real;
|
||||
}
|
||||
}
|
||||
|
||||
// To verify that the NonZero types in this file's macro invocations correspond
|
||||
//
|
||||
// perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2'
|
||||
//
|
||||
// NB this does not check that the main c_* types are right.
|
||||
|
||||
macro_rules! type_alias {
|
||||
{
|
||||
$Docfile:tt, $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty;
|
||||
$( $Cfg:tt )*
|
||||
} => {
|
||||
type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* }
|
||||
|
||||
#[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")]
|
||||
#[unstable(feature = "raw_os_nonzero", issue = "82363")]
|
||||
$( $Cfg )*
|
||||
pub type $NZAlias = $NZReal;
|
||||
}
|
||||
}
|
||||
|
||||
type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8;
|
||||
#[cfg(any(
|
||||
all(
|
||||
target_os = "linux",
|
||||
@ -52,10 +86,8 @@
|
||||
)
|
||||
),
|
||||
all(target_os = "fuchsia", target_arch = "aarch64")
|
||||
))]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_char = u8;
|
||||
#[doc(include = "char.md")]
|
||||
))]}
|
||||
type_alias! { "char.md", c_char = i8, NonZero_c_char = NonZeroI8;
|
||||
#[cfg(not(any(
|
||||
all(
|
||||
target_os = "linux",
|
||||
@ -96,55 +128,25 @@
|
||||
)
|
||||
),
|
||||
all(target_os = "fuchsia", target_arch = "aarch64")
|
||||
)))]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_char = i8;
|
||||
#[doc(include = "schar.md")]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_schar = i8;
|
||||
#[doc(include = "uchar.md")]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_uchar = u8;
|
||||
#[doc(include = "short.md")]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_short = i16;
|
||||
#[doc(include = "ushort.md")]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_ushort = u16;
|
||||
#[doc(include = "int.md")]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_int = i32;
|
||||
#[doc(include = "uint.md")]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_uint = u32;
|
||||
#[doc(include = "long.md")]
|
||||
#[cfg(any(target_pointer_width = "32", windows))]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_long = i32;
|
||||
#[doc(include = "ulong.md")]
|
||||
#[cfg(any(target_pointer_width = "32", windows))]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_ulong = u32;
|
||||
#[doc(include = "long.md")]
|
||||
#[cfg(all(target_pointer_width = "64", not(windows)))]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_long = i64;
|
||||
#[doc(include = "ulong.md")]
|
||||
#[cfg(all(target_pointer_width = "64", not(windows)))]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_ulong = u64;
|
||||
#[doc(include = "longlong.md")]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_longlong = i64;
|
||||
#[doc(include = "ulonglong.md")]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_ulonglong = u64;
|
||||
#[doc(include = "float.md")]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_float = f32;
|
||||
#[doc(include = "double.md")]
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
pub type c_double = f64;
|
||||
)))]}
|
||||
type_alias! { "schar.md", c_schar = i8, NonZero_c_schar = NonZeroI8; }
|
||||
type_alias! { "uchar.md", c_uchar = u8, NonZero_c_uchar = NonZeroU8; }
|
||||
type_alias! { "short.md", c_short = i16, NonZero_c_short = NonZeroI16; }
|
||||
type_alias! { "ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; }
|
||||
type_alias! { "int.md", c_int = i32, NonZero_c_int = NonZeroI32; }
|
||||
type_alias! { "uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; }
|
||||
type_alias! { "long.md", c_long = i32, NonZero_c_long = NonZeroI32;
|
||||
#[cfg(any(target_pointer_width = "32", windows))] }
|
||||
type_alias! { "ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32;
|
||||
#[cfg(any(target_pointer_width = "32", windows))] }
|
||||
type_alias! { "long.md", c_long = i64, NonZero_c_long = NonZeroI64;
|
||||
#[cfg(all(target_pointer_width = "64", not(windows)))] }
|
||||
type_alias! { "ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64;
|
||||
#[cfg(all(target_pointer_width = "64", not(windows)))] }
|
||||
type_alias! { "longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; }
|
||||
type_alias! { "ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; }
|
||||
type_alias_no_nz! { "float.md", c_float = f32; }
|
||||
type_alias_no_nz! { "double.md", c_double = f64; }
|
||||
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
#[doc(no_inline)]
|
||||
|
@ -1519,7 +1519,7 @@ fn normalize(cx: &mut DocContext<'tcx>, ty: Ty<'_>) -> Option<Ty<'tcx>> {
|
||||
let lifted = ty.lift_to_tcx(cx.tcx).unwrap();
|
||||
let normalized = cx.tcx.infer_ctxt().enter(|infcx| {
|
||||
infcx
|
||||
.at(&ObligationCause::dummy(), cx.param_env.get())
|
||||
.at(&ObligationCause::dummy(), cx.param_env)
|
||||
.normalize(lifted)
|
||||
.map(|resolved| infcx.resolve_vars_if_possible(resolved.value))
|
||||
});
|
||||
|
@ -26,10 +26,7 @@
|
||||
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use std::{
|
||||
cell::{Cell, RefCell},
|
||||
collections::hash_map::Entry,
|
||||
};
|
||||
use std::{cell::RefCell, collections::hash_map::Entry};
|
||||
|
||||
use crate::clean;
|
||||
use crate::clean::inline::build_external_trait;
|
||||
@ -49,7 +46,7 @@
|
||||
/// Used for normalization.
|
||||
///
|
||||
/// Most of this logic is copied from rustc_lint::late.
|
||||
crate param_env: Cell<ParamEnv<'tcx>>,
|
||||
crate param_env: ParamEnv<'tcx>,
|
||||
/// Later on moved into `cache`
|
||||
crate renderinfo: RefCell<RenderInfo>,
|
||||
/// Later on moved through `clean::Crate` into `cache`
|
||||
@ -67,7 +64,7 @@
|
||||
crate ct_substs: RefCell<FxHashMap<DefId, clean::Constant>>,
|
||||
/// Table synthetic type parameter for `impl Trait` in argument position -> bounds
|
||||
crate impl_trait_bounds: RefCell<FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>>,
|
||||
crate fake_def_ids: RefCell<FxHashMap<CrateNum, DefIndex>>,
|
||||
crate fake_def_ids: FxHashMap<CrateNum, DefIndex>,
|
||||
/// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
|
||||
// FIXME(eddyb) make this a `ty::TraitRef<'tcx>` set.
|
||||
crate generated_synthetics: RefCell<FxHashSet<(Ty<'tcx>, DefId)>>,
|
||||
@ -89,9 +86,9 @@ impl<'tcx> DocContext<'tcx> {
|
||||
}
|
||||
|
||||
crate fn with_param_env<T, F: FnOnce(&mut Self) -> T>(&mut self, def_id: DefId, f: F) -> T {
|
||||
let old_param_env = self.param_env.replace(self.tcx.param_env(def_id));
|
||||
let old_param_env = mem::replace(&mut self.param_env, self.tcx.param_env(def_id));
|
||||
let ret = f(self);
|
||||
self.param_env.set(old_param_env);
|
||||
self.param_env = old_param_env;
|
||||
ret
|
||||
}
|
||||
|
||||
@ -140,16 +137,14 @@ impl<'tcx> DocContext<'tcx> {
|
||||
/// [`RefCell`]: std::cell::RefCell
|
||||
/// [`Debug`]: std::fmt::Debug
|
||||
/// [`clean::Item`]: crate::clean::types::Item
|
||||
crate fn next_def_id(&self, crate_num: CrateNum) -> DefId {
|
||||
let mut fake_ids = self.fake_def_ids.borrow_mut();
|
||||
|
||||
let def_index = match fake_ids.entry(crate_num) {
|
||||
crate fn next_def_id(&mut self, crate_num: CrateNum) -> DefId {
|
||||
let def_index = match self.fake_def_ids.entry(crate_num) {
|
||||
Entry::Vacant(e) => {
|
||||
let num_def_idx = {
|
||||
let num_def_idx = if crate_num == LOCAL_CRATE {
|
||||
self.tcx.hir().definitions().def_path_table().num_def_ids()
|
||||
} else {
|
||||
self.enter_resolver(|r| r.cstore().num_def_ids(crate_num))
|
||||
self.resolver.borrow_mut().access(|r| r.cstore().num_def_ids(crate_num))
|
||||
};
|
||||
|
||||
DefIndex::from_usize(num_def_idx)
|
||||
@ -511,7 +506,7 @@ pub(crate) fn init_lints<F>(
|
||||
let mut ctxt = DocContext {
|
||||
tcx,
|
||||
resolver,
|
||||
param_env: Cell::new(ParamEnv::empty()),
|
||||
param_env: ParamEnv::empty(),
|
||||
external_traits: Default::default(),
|
||||
active_extern_traits: Default::default(),
|
||||
renderinfo: RefCell::new(renderinfo),
|
||||
|
@ -1124,6 +1124,7 @@ fn push(s: &mut String, text_length: &mut usize, text: &str) {
|
||||
Event::HardBreak | Event::SoftBreak => s.push(' '),
|
||||
Event::Start(Tag::CodeBlock(..)) => break,
|
||||
Event::End(Tag::Paragraph) => break,
|
||||
Event::End(Tag::Heading(..)) => break,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -230,6 +230,7 @@ fn t(input: &str, expect: &str) {
|
||||
t("code `let x = i32;` ...", "code `let x = i32;` ...");
|
||||
t("type `Type<'static>` ...", "type `Type<'static>` ...");
|
||||
t("# top header", "top header");
|
||||
t("# top header\n\nfollowed by some text", "top header");
|
||||
t("## header", "header");
|
||||
t("first paragraph\n\nsecond paragraph", "first paragraph");
|
||||
t("```\nfn main() {}\n```", "");
|
||||
|
@ -1548,7 +1548,10 @@ fn render_item(&self, it: &clean::Item, pushname: bool) -> String {
|
||||
}
|
||||
title.push_str(" - Rust");
|
||||
let tyname = it.type_();
|
||||
let desc = if it.is_crate() {
|
||||
let desc = it.doc_value().as_ref().map(|doc| plain_text_summary(&doc));
|
||||
let desc = if let Some(desc) = desc {
|
||||
desc
|
||||
} else if it.is_crate() {
|
||||
format!("API documentation for the Rust `{}` crate.", self.shared.layout.krate)
|
||||
} else {
|
||||
format!(
|
||||
|
24
src/test/rustdoc/description.rs
Normal file
24
src/test/rustdoc/description.rs
Normal file
@ -0,0 +1,24 @@
|
||||
#![crate_name = "foo"]
|
||||
//! # Description test crate
|
||||
//!
|
||||
//! This is the contents of the test crate docstring.
|
||||
//! It should not show up in the description.
|
||||
|
||||
// @has 'foo/index.html' '//meta[@name="description"]/@content' \
|
||||
// 'Description test crate'
|
||||
// @!has - '//meta[@name="description"]/@content' 'should not show up'
|
||||
|
||||
// @has 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' \
|
||||
// 'First paragraph description.'
|
||||
// @!has - '//meta[@name="description"]/@content' 'Second paragraph'
|
||||
/// First paragraph description.
|
||||
///
|
||||
/// Second paragraph should not show up.
|
||||
pub mod foo_mod {
|
||||
pub struct __Thing {}
|
||||
}
|
||||
|
||||
// @has 'foo/fn.foo_fn.html' '//meta[@name="description"]/@content' \
|
||||
// 'Only paragraph.'
|
||||
/// Only paragraph.
|
||||
pub fn foo_fn() {}
|
14
src/test/rustdoc/description_default.rs
Normal file
14
src/test/rustdoc/description_default.rs
Normal file
@ -0,0 +1,14 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// @has 'foo/index.html' '//meta[@name="description"]/@content' \
|
||||
// 'API documentation for the Rust `foo` crate.'
|
||||
|
||||
// @has 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' \
|
||||
// 'API documentation for the Rust `foo_mod` mod in crate `foo`.'
|
||||
pub mod foo_mod {
|
||||
pub struct __Thing {}
|
||||
}
|
||||
|
||||
// @has 'foo/fn.foo_fn.html' '//meta[@name="description"]/@content' \
|
||||
// 'API documentation for the Rust `foo_fn` fn in crate `foo`.'
|
||||
pub fn foo_fn() {}
|
@ -32,7 +32,7 @@ fn main() {
|
||||
let w = SingleFoo { };
|
||||
//~^ ERROR missing field `x` in initializer of `SingleFoo`
|
||||
let x = PluralFoo {x: 1};
|
||||
//~^ ERROR missing fields `y`, `z` in initializer of `PluralFoo`
|
||||
//~^ ERROR missing fields `y` and `z` in initializer of `PluralFoo`
|
||||
let y = TruncatedFoo{x:1};
|
||||
//~^ missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo`
|
||||
let z = TruncatedPluralFoo{x:1};
|
||||
|
@ -4,11 +4,11 @@ error[E0063]: missing field `x` in initializer of `SingleFoo`
|
||||
LL | let w = SingleFoo { };
|
||||
| ^^^^^^^^^ missing `x`
|
||||
|
||||
error[E0063]: missing fields `y`, `z` in initializer of `PluralFoo`
|
||||
error[E0063]: missing fields `y` and `z` in initializer of `PluralFoo`
|
||||
--> $DIR/E0063.rs:34:13
|
||||
|
|
||||
LL | let x = PluralFoo {x: 1};
|
||||
| ^^^^^^^^^ missing `y`, `z`
|
||||
| ^^^^^^^^^ missing `y` and `z`
|
||||
|
||||
error[E0063]: missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo`
|
||||
--> $DIR/E0063.rs:36:13
|
||||
|
@ -23,7 +23,7 @@ fn wrong() {
|
||||
foo::Enum::Variant { x: () };
|
||||
//~^ ERROR missing field `y` in initializer of `Enum`
|
||||
foo::Enum::Variant { };
|
||||
//~^ ERROR missing fields `x`, `y` in initializer of `Enum`
|
||||
//~^ ERROR missing fields `x` and `y` in initializer of `Enum`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -22,11 +22,11 @@ error[E0063]: missing field `y` in initializer of `Enum`
|
||||
LL | foo::Enum::Variant { x: () };
|
||||
| ^^^^^^^^^^^^^^^^^^ missing `y`
|
||||
|
||||
error[E0063]: missing fields `x`, `y` in initializer of `Enum`
|
||||
error[E0063]: missing fields `x` and `y` in initializer of `Enum`
|
||||
--> $DIR/issue-79593.rs:25:5
|
||||
|
|
||||
LL | foo::Enum::Variant { };
|
||||
| ^^^^^^^^^^^^^^^^^^ missing `x`, `y`
|
||||
| ^^^^^^^^^^^^^^^^^^ missing `x` and `y`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
33
src/test/ui/layout/hexagon-enum.rs
Normal file
33
src/test/ui/layout/hexagon-enum.rs
Normal file
@ -0,0 +1,33 @@
|
||||
// compile-flags: --target hexagon-unknown-linux-musl
|
||||
//
|
||||
// Verify that the hexagon targets implement the repr(C) for enums correctly.
|
||||
//
|
||||
// See #82100
|
||||
#![feature(never_type, rustc_attrs, type_alias_impl_trait, no_core, lang_items)]
|
||||
#![crate_type = "lib"]
|
||||
#![no_core]
|
||||
|
||||
#[lang="sized"]
|
||||
trait Sized {}
|
||||
|
||||
#[rustc_layout(debug)]
|
||||
#[repr(C)]
|
||||
enum A { Apple } //~ ERROR: layout_of
|
||||
|
||||
#[rustc_layout(debug)]
|
||||
#[repr(C)]
|
||||
enum B { Banana = 255, } //~ ERROR: layout_of
|
||||
|
||||
#[rustc_layout(debug)]
|
||||
#[repr(C)]
|
||||
enum C { Chaenomeles = 256, } //~ ERROR: layout_of
|
||||
|
||||
#[rustc_layout(debug)]
|
||||
#[repr(C)]
|
||||
enum P { Peach = 0x1000_0000isize, } //~ ERROR: layout_of
|
||||
|
||||
const TANGERINE: usize = 0x8100_0000; // hack to get negative numbers without negation operator!
|
||||
|
||||
#[rustc_layout(debug)]
|
||||
#[repr(C)]
|
||||
enum T { Tangerine = TANGERINE as isize } //~ ERROR: layout_of
|
442
src/test/ui/layout/hexagon-enum.stderr
Normal file
442
src/test/ui/layout/hexagon-enum.stderr
Normal file
@ -0,0 +1,442 @@
|
||||
error: layout_of(A) = Layout {
|
||||
fields: Arbitrary {
|
||||
offsets: [
|
||||
Size {
|
||||
raw: 0,
|
||||
},
|
||||
],
|
||||
memory_index: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=0,
|
||||
},
|
||||
tag_encoding: Direct,
|
||||
tag_field: 0,
|
||||
variants: [
|
||||
Layout {
|
||||
fields: Arbitrary {
|
||||
offsets: [],
|
||||
memory_index: [],
|
||||
},
|
||||
variants: Single {
|
||||
index: 0,
|
||||
},
|
||||
abi: Aggregate {
|
||||
sized: true,
|
||||
},
|
||||
largest_niche: None,
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align {
|
||||
pow2: 0,
|
||||
},
|
||||
pref: Align {
|
||||
pow2: 0,
|
||||
},
|
||||
},
|
||||
size: Size {
|
||||
raw: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=0,
|
||||
},
|
||||
),
|
||||
largest_niche: Some(
|
||||
Niche {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=0,
|
||||
},
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align {
|
||||
pow2: 0,
|
||||
},
|
||||
pref: Align {
|
||||
pow2: 0,
|
||||
},
|
||||
},
|
||||
size: Size {
|
||||
raw: 1,
|
||||
},
|
||||
}
|
||||
--> $DIR/hexagon-enum.rs:15:1
|
||||
|
|
||||
LL | enum A { Apple }
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: layout_of(B) = Layout {
|
||||
fields: Arbitrary {
|
||||
offsets: [
|
||||
Size {
|
||||
raw: 0,
|
||||
},
|
||||
],
|
||||
memory_index: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
),
|
||||
valid_range: 255..=255,
|
||||
},
|
||||
tag_encoding: Direct,
|
||||
tag_field: 0,
|
||||
variants: [
|
||||
Layout {
|
||||
fields: Arbitrary {
|
||||
offsets: [],
|
||||
memory_index: [],
|
||||
},
|
||||
variants: Single {
|
||||
index: 0,
|
||||
},
|
||||
abi: Aggregate {
|
||||
sized: true,
|
||||
},
|
||||
largest_niche: None,
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align {
|
||||
pow2: 0,
|
||||
},
|
||||
pref: Align {
|
||||
pow2: 0,
|
||||
},
|
||||
},
|
||||
size: Size {
|
||||
raw: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
),
|
||||
valid_range: 255..=255,
|
||||
},
|
||||
),
|
||||
largest_niche: Some(
|
||||
Niche {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
),
|
||||
valid_range: 255..=255,
|
||||
},
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align {
|
||||
pow2: 0,
|
||||
},
|
||||
pref: Align {
|
||||
pow2: 0,
|
||||
},
|
||||
},
|
||||
size: Size {
|
||||
raw: 1,
|
||||
},
|
||||
}
|
||||
--> $DIR/hexagon-enum.rs:19:1
|
||||
|
|
||||
LL | enum B { Banana = 255, }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: layout_of(C) = Layout {
|
||||
fields: Arbitrary {
|
||||
offsets: [
|
||||
Size {
|
||||
raw: 0,
|
||||
},
|
||||
],
|
||||
memory_index: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
value: Int(
|
||||
I16,
|
||||
false,
|
||||
),
|
||||
valid_range: 256..=256,
|
||||
},
|
||||
tag_encoding: Direct,
|
||||
tag_field: 0,
|
||||
variants: [
|
||||
Layout {
|
||||
fields: Arbitrary {
|
||||
offsets: [],
|
||||
memory_index: [],
|
||||
},
|
||||
variants: Single {
|
||||
index: 0,
|
||||
},
|
||||
abi: Aggregate {
|
||||
sized: true,
|
||||
},
|
||||
largest_niche: None,
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align {
|
||||
pow2: 1,
|
||||
},
|
||||
pref: Align {
|
||||
pow2: 1,
|
||||
},
|
||||
},
|
||||
size: Size {
|
||||
raw: 2,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
value: Int(
|
||||
I16,
|
||||
false,
|
||||
),
|
||||
valid_range: 256..=256,
|
||||
},
|
||||
),
|
||||
largest_niche: Some(
|
||||
Niche {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I16,
|
||||
false,
|
||||
),
|
||||
valid_range: 256..=256,
|
||||
},
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align {
|
||||
pow2: 1,
|
||||
},
|
||||
pref: Align {
|
||||
pow2: 1,
|
||||
},
|
||||
},
|
||||
size: Size {
|
||||
raw: 2,
|
||||
},
|
||||
}
|
||||
--> $DIR/hexagon-enum.rs:23:1
|
||||
|
|
||||
LL | enum C { Chaenomeles = 256, }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: layout_of(P) = Layout {
|
||||
fields: Arbitrary {
|
||||
offsets: [
|
||||
Size {
|
||||
raw: 0,
|
||||
},
|
||||
],
|
||||
memory_index: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 268435456..=268435456,
|
||||
},
|
||||
tag_encoding: Direct,
|
||||
tag_field: 0,
|
||||
variants: [
|
||||
Layout {
|
||||
fields: Arbitrary {
|
||||
offsets: [],
|
||||
memory_index: [],
|
||||
},
|
||||
variants: Single {
|
||||
index: 0,
|
||||
},
|
||||
abi: Aggregate {
|
||||
sized: true,
|
||||
},
|
||||
largest_niche: None,
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align {
|
||||
pow2: 2,
|
||||
},
|
||||
pref: Align {
|
||||
pow2: 2,
|
||||
},
|
||||
},
|
||||
size: Size {
|
||||
raw: 4,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 268435456..=268435456,
|
||||
},
|
||||
),
|
||||
largest_niche: Some(
|
||||
Niche {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 268435456..=268435456,
|
||||
},
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align {
|
||||
pow2: 2,
|
||||
},
|
||||
pref: Align {
|
||||
pow2: 2,
|
||||
},
|
||||
},
|
||||
size: Size {
|
||||
raw: 4,
|
||||
},
|
||||
}
|
||||
--> $DIR/hexagon-enum.rs:27:1
|
||||
|
|
||||
LL | enum P { Peach = 0x1000_0000isize, }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: layout_of(T) = Layout {
|
||||
fields: Arbitrary {
|
||||
offsets: [
|
||||
Size {
|
||||
raw: 0,
|
||||
},
|
||||
],
|
||||
memory_index: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
),
|
||||
valid_range: 2164260864..=2164260864,
|
||||
},
|
||||
tag_encoding: Direct,
|
||||
tag_field: 0,
|
||||
variants: [
|
||||
Layout {
|
||||
fields: Arbitrary {
|
||||
offsets: [],
|
||||
memory_index: [],
|
||||
},
|
||||
variants: Single {
|
||||
index: 0,
|
||||
},
|
||||
abi: Aggregate {
|
||||
sized: true,
|
||||
},
|
||||
largest_niche: None,
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align {
|
||||
pow2: 2,
|
||||
},
|
||||
pref: Align {
|
||||
pow2: 2,
|
||||
},
|
||||
},
|
||||
size: Size {
|
||||
raw: 4,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
),
|
||||
valid_range: 2164260864..=2164260864,
|
||||
},
|
||||
),
|
||||
largest_niche: Some(
|
||||
Niche {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
),
|
||||
valid_range: 2164260864..=2164260864,
|
||||
},
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
abi: Align {
|
||||
pow2: 2,
|
||||
},
|
||||
pref: Align {
|
||||
pow2: 2,
|
||||
},
|
||||
},
|
||||
size: Size {
|
||||
raw: 4,
|
||||
},
|
||||
}
|
||||
--> $DIR/hexagon-enum.rs:33:1
|
||||
|
|
||||
LL | enum T { Tangerine = TANGERINE as isize }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
@ -7,6 +7,6 @@ fn main() {
|
||||
let bar = 1.5f32;
|
||||
let _ = Foo { bar.into(), bat: -1, . };
|
||||
//~^ ERROR expected one of
|
||||
//~| ERROR missing fields `bar`, `baz` in initializer of `Foo`
|
||||
//~| ERROR missing fields `bar` and `baz` in initializer of `Foo`
|
||||
//~| ERROR expected identifier, found `.`
|
||||
}
|
||||
|
@ -26,11 +26,11 @@ error[E0063]: missing field `bat` in initializer of `Foo`
|
||||
LL | let _ = Foo { bar: .5, baz: 42 };
|
||||
| ^^^ missing `bat`
|
||||
|
||||
error[E0063]: missing fields `bar`, `baz` in initializer of `Foo`
|
||||
error[E0063]: missing fields `bar` and `baz` in initializer of `Foo`
|
||||
--> $DIR/issue-52496.rs:8:13
|
||||
|
|
||||
LL | let _ = Foo { bar.into(), bat: -1, . };
|
||||
| ^^^ missing `bar`, `baz`
|
||||
| ^^^ missing `bar` and `baz`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
@ -5,5 +5,5 @@ fn main() {
|
||||
//~^ ERROR expected identifier, found `0`
|
||||
//~| ERROR expected identifier, found `1`
|
||||
//~| ERROR expected identifier, found `2`
|
||||
//~| ERROR missing fields `0`, `1`, `2` in initializer of `Rgb`
|
||||
//~| ERROR missing fields `0`, `1` and `2` in initializer of `Rgb`
|
||||
}
|
||||
|
@ -22,11 +22,11 @@ LL | let _ = Rgb { 0, 1, 2 };
|
||||
| |
|
||||
| while parsing this struct
|
||||
|
||||
error[E0063]: missing fields `0`, `1`, `2` in initializer of `Rgb`
|
||||
error[E0063]: missing fields `0`, `1` and `2` in initializer of `Rgb`
|
||||
--> $DIR/struct-field-numeric-shorthand.rs:4:13
|
||||
|
|
||||
LL | let _ = Rgb { 0, 1, 2 };
|
||||
| ^^^ missing `0`, `1`, `2`
|
||||
| ^^^ missing `0`, `1` and `2`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user