(sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)),
(sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
(sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
+ (
+ sym::target_has_atomic_equal_alignment,
+ sym::cfg_target_has_atomic,
+ cfg_fn!(cfg_target_has_atomic),
+ ),
(sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)),
(sym::version, sym::cfg_version, cfg_fn!(cfg_version)),
];
}
/// Check if this enum can be safely exported based on the "nullable pointer optimization". If it
-/// can, return the the type that `ty` can be safely converted to, otherwise return `None`.
+/// can, return the type that `ty` can be safely converted to, otherwise return `None`.
/// Currently restricted to function pointers, boxes, references, `core::num::NonZero*`,
/// `core::ptr::NonNull`, and `#[repr(transparent)]` newtypes.
/// FIXME: This duplicates code in codegen.
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, OnceCell};
+use rustc_errors::ErrorReported;
use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
use rustc_hir as hir;
&self,
tcx: TyCtxt<'tcx>,
id: DefIndex,
- ) -> Option<&'tcx [mir::abstract_const::Node<'tcx>]> {
+ ) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
self.root
.tables
.mir_abstract_consts
.get(self, id)
.filter(|_| !self.is_proc_macro(id))
- .map_or(None, |v| Some(v.decode((self, tcx))))
+ .map_or(Ok(None), |v| Ok(Some(v.decode((self, tcx)))))
}
fn get_unused_generic_params(&self, id: DefIndex) -> FiniteBitSet<u32> {
}
let abstract_const = self.tcx.mir_abstract_const(def_id);
- if let Some(abstract_const) = abstract_const {
+ if let Ok(Some(abstract_const)) = abstract_const {
record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const);
}
}
});
record!(self.tables.visibility[def_id] <-
ty::Visibility::from_hir(&item.vis, item.hir_id, tcx));
- record!(self.tables.span[def_id] <- item.span);
+ record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
record!(self.tables.attributes[def_id] <- item.attrs);
// FIXME(eddyb) there should be a nicer way to do this.
match item.kind {
TooGeneric,
}
+impl From<ErrorReported> for ErrorHandled {
+ fn from(err: ErrorReported) -> ErrorHandled {
+ ErrorHandled::Reported(err)
+ }
+}
+
CloneTypeFoldableAndLiftImpls! {
ErrorHandled,
}
self.cache = OnceCell::new();
}
- /// Returns the the predecessor graph for this MIR.
+ /// Returns the predecessor graph for this MIR.
#[inline]
pub(super) fn compute(
&self,
/// Try to build an abstract representation of the given constant.
query mir_abstract_const(
key: DefId
- ) -> Option<&'tcx [mir::abstract_const::Node<'tcx>]> {
+ ) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
desc {
|tcx| "building an abstract representation for {}", tcx.def_path_str(key),
}
/// Try to build an abstract representation of the given constant.
query mir_abstract_const_of_const_arg(
key: (LocalDefId, DefId)
- ) -> Option<&'tcx [mir::abstract_const::Node<'tcx>]> {
+ ) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
desc {
|tcx|
"building an abstract representation for the const argument {}",
/// Pushes a member constraint into the set.
///
/// The input member constraint `m_c` is in the form produced by
- /// the the `rustc_middle::infer` code.
+ /// the `rustc_middle::infer` code.
///
/// The `to_region_vid` callback fn is used to convert the regions
/// within into `RegionVid` format -- it typically consults the
None => {
// Deallocating global memory -- always an error
return Err(match self.tcx.get_global_alloc(ptr.alloc_id) {
- Some(GlobalAlloc::Function(..)) => err_ub_format!("deallocating a function"),
+ Some(GlobalAlloc::Function(..)) => {
+ err_ub_format!("deallocating {}, which is a function", ptr.alloc_id)
+ }
Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => {
- err_ub_format!("deallocating static memory")
+ err_ub_format!("deallocating {}, which is static memory", ptr.alloc_id)
}
None => err_ub!(PointerUseAfterFree(ptr.alloc_id)),
}
if alloc_kind != kind {
throw_ub_format!(
- "deallocating {} memory using {} deallocation operation",
+ "deallocating {}, which is {} memory, using {} deallocation operation",
+ ptr.alloc_id,
alloc_kind,
kind
);
if let Some((size, align)) = old_size_and_align {
if size != alloc.size || align != alloc.align {
throw_ub_format!(
- "incorrect layout on deallocation: allocation has size {} and alignment {}, but gave size {} and alignment {}",
+ "incorrect layout on deallocation: {} has size {} and alignment {}, but gave size {} and alignment {}",
+ ptr.alloc_id,
alloc.size.bytes(),
alloc.align.bytes(),
size.bytes(),
let target_block = self.cfg.start_new_block();
let mut schedule_drops = true;
// We keep a stack of all of the bindings and type asciptions
- // from the the parent candidates that we visit, that also need to
+ // from the parent candidates that we visit, that also need to
// be bound for each candidate.
traverse_candidate(
candidate,
/// Parse a type suitable for a function or function pointer parameter.
/// The difference from `parse_ty` is that this version allows `...`
- /// (`CVarArgs`) at the top level of the the type.
+ /// (`CVarArgs`) at the top level of the type.
pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
self.parse_ty_common(AllowPlus::Yes, RecoverQPath::Yes, AllowCVariadic::Yes)
}
use rustc_data_structures::impl_stable_hash_via_hash;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_target::abi::{Align, TargetDataLayout};
use rustc_target::spec::{Target, TargetTriple};
use crate::parse::CrateConfig;
let min_atomic_width = sess.target.target.min_atomic_width();
let max_atomic_width = sess.target.target.max_atomic_width();
let atomic_cas = sess.target.target.options.atomic_cas;
+ let layout = TargetDataLayout::parse(&sess.target.target).unwrap_or_else(|err| {
+ sess.fatal(&err);
+ });
let mut ret = FxHashSet::default();
ret.reserve(6); // the minimum number of insertions
if sess.target.target.options.has_elf_tls {
ret.insert((sym::target_thread_local, None));
}
- for &i in &[8, 16, 32, 64, 128] {
+ for &(i, align) in &[
+ (8, layout.i8_align.abi),
+ (16, layout.i16_align.abi),
+ (32, layout.i32_align.abi),
+ (64, layout.i64_align.abi),
+ (128, layout.i128_align.abi),
+ ] {
if i >= min_atomic_width && i <= max_atomic_width {
- let mut insert_atomic = |s| {
+ let mut insert_atomic = |s, align: Align| {
ret.insert((sym::target_has_atomic_load_store, Some(Symbol::intern(s))));
if atomic_cas {
ret.insert((sym::target_has_atomic, Some(Symbol::intern(s))));
}
+ if align.bits() == i {
+ ret.insert((sym::target_has_atomic_equal_alignment, Some(Symbol::intern(s))));
+ }
};
let s = i.to_string();
- insert_atomic(&s);
+ insert_atomic(&s, align);
if &s == wordsz {
- insert_atomic("ptr");
+ insert_atomic("ptr", layout.pointer_align.abi);
}
}
}
// called `sym::proc_macro` because then it's easy to mistakenly think it
// represents "proc_macro".
//
- // As well as the symbols listed, there are symbols for the the strings
+ // As well as the symbols listed, there are symbols for the strings
// "0", "1", ..., "9", which are accessible via `sym::integer`.
//
// The proc macro will abort if symbols are not in alphabetical order (as
target_feature,
target_feature_11,
target_has_atomic,
+ target_has_atomic_equal_alignment,
target_has_atomic_load_store,
target_os,
target_pointer_width,
//! ## No interop with C required
//!
//! By default the `crt-static` target feature is enabled, and when enabled
-//! this means that the the bundled version of `libc.a` found in `liblibc.rlib`
+//! this means that the bundled version of `libc.a` found in `liblibc.rlib`
//! is used. This isn't intended really for interoperation with a C because it
//! may be the case that Rust's bundled C library is incompatible with a
//! foreign-compiled C library. In this use case, though, we use `rust-lld` and
#![feature(box_patterns)]
#![feature(drain_filter)]
#![feature(in_band_lifetimes)]
+#![feature(never_type)]
#![feature(crate_visibility_modifier)]
#![feature(or_patterns)]
#![recursion_limit = "512"] // For rustdoc
//! In this case we try to build an abstract representation of this constant using
//! `mir_abstract_const` which can then be checked for structural equality with other
//! generic constants mentioned in the `caller_bounds` of the current environment.
+use rustc_errors::ErrorReported;
use rustc_hir::def::DefKind;
use rustc_index::bit_set::BitSet;
use rustc_index::vec::IndexVec;
) -> Result<(), ErrorHandled> {
debug!("is_const_evaluatable({:?}, {:?})", def, substs);
if infcx.tcx.features().const_evaluatable_checked {
- if let Some(ct) = AbstractConst::new(infcx.tcx, def, substs) {
+ if let Some(ct) = AbstractConst::new(infcx.tcx, def, substs)? {
for pred in param_env.caller_bounds() {
match pred.skip_binders() {
ty::PredicateAtom::ConstEvaluatable(b_def, b_substs) => {
if b_def == def && b_substs == substs {
debug!("is_const_evaluatable: caller_bound ~~> ok");
return Ok(());
- } else if AbstractConst::new(infcx.tcx, b_def, b_substs)
+ } else if AbstractConst::new(infcx.tcx, b_def, b_substs)?
.map_or(false, |b_ct| try_unify(infcx.tcx, ct, b_ct))
{
debug!("is_const_evaluatable: abstract_const ~~> ok");
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<DefId>,
substs: SubstsRef<'tcx>,
- ) -> Option<AbstractConst<'tcx>> {
+ ) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
let inner = match (def.did.as_local(), def.const_param_did) {
(Some(did), Some(param_did)) => {
tcx.mir_abstract_const_of_const_arg((did, param_did))?
_ => tcx.mir_abstract_const(def.did)?,
};
- Some(AbstractConst { inner, substs })
+ Ok(inner.map(|inner| AbstractConst { inner, substs }))
}
#[inline]
}
impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
- fn new(tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>) -> Option<AbstractConstBuilder<'a, 'tcx>> {
- // We only allow consts without control flow, so
- // we check for cycles here which simplifies the
- // rest of this implementation.
- if body.is_cfg_cyclic() {
- return None;
- }
+ fn error(&mut self, span: Option<Span>, msg: &str) -> Result<!, ErrorReported> {
+ self.tcx
+ .sess
+ .struct_span_err(self.body.span, "overly complex generic constant")
+ .span_label(span.unwrap_or(self.body.span), msg)
+ .help("consider moving this anonymous constant into a `const` function")
+ .emit();
- // We don't have to look at concrete constants, as we
- // can just evaluate them.
- if !body.is_polymorphic {
- return None;
- }
+ Err(ErrorReported)
+ }
- Some(AbstractConstBuilder {
+ fn new(
+ tcx: TyCtxt<'tcx>,
+ body: &'a mir::Body<'tcx>,
+ ) -> Result<Option<AbstractConstBuilder<'a, 'tcx>>, ErrorReported> {
+ let mut builder = AbstractConstBuilder {
tcx,
body,
nodes: IndexVec::new(),
locals: IndexVec::from_elem(NodeId::MAX, &body.local_decls),
checked_op_locals: BitSet::new_empty(body.local_decls.len()),
- })
+ };
+
+ // We don't have to look at concrete constants, as we
+ // can just evaluate them.
+ if !body.is_polymorphic {
+ return Ok(None);
+ }
+
+ // We only allow consts without control flow, so
+ // we check for cycles here which simplifies the
+ // rest of this implementation.
+ if body.is_cfg_cyclic() {
+ builder.error(None, "cyclic anonymous constants are forbidden")?;
+ }
+
+ Ok(Some(builder))
}
- fn operand_to_node(&mut self, op: &mir::Operand<'tcx>) -> Option<NodeId> {
- debug!("operand_to_node: op={:?}", op);
+
+ fn place_to_local(
+ &mut self,
+ span: Span,
+ p: &mir::Place<'tcx>,
+ ) -> Result<mir::Local, ErrorReported> {
const ZERO_FIELD: mir::Field = mir::Field::from_usize(0);
+ // Do not allow any projections.
+ //
+ // One exception are field accesses on the result of checked operations,
+ // which are required to support things like `1 + 2`.
+ if let Some(p) = p.as_local() {
+ debug_assert!(!self.checked_op_locals.contains(p));
+ Ok(p)
+ } else if let &[mir::ProjectionElem::Field(ZERO_FIELD, _)] = p.projection.as_ref() {
+ // Only allow field accesses if the given local
+ // contains the result of a checked operation.
+ if self.checked_op_locals.contains(p.local) {
+ Ok(p.local)
+ } else {
+ self.error(Some(span), "unsupported projection")?;
+ }
+ } else {
+ self.error(Some(span), "unsupported projection")?;
+ }
+ }
+
+ fn operand_to_node(
+ &mut self,
+ span: Span,
+ op: &mir::Operand<'tcx>,
+ ) -> Result<NodeId, ErrorReported> {
+ debug!("operand_to_node: op={:?}", op);
match op {
mir::Operand::Copy(p) | mir::Operand::Move(p) => {
- // Do not allow any projections.
- //
- // One exception are field accesses on the result of checked operations,
- // which are required to support things like `1 + 2`.
- if let Some(p) = p.as_local() {
- debug_assert!(!self.checked_op_locals.contains(p));
- Some(self.locals[p])
- } else if let &[mir::ProjectionElem::Field(ZERO_FIELD, _)] = p.projection.as_ref() {
- // Only allow field accesses if the given local
- // contains the result of a checked operation.
- if self.checked_op_locals.contains(p.local) {
- Some(self.locals[p.local])
- } else {
- None
- }
- } else {
- None
- }
+ let local = self.place_to_local(span, p)?;
+ Ok(self.locals[local])
}
- mir::Operand::Constant(ct) => Some(self.nodes.push(Node::Leaf(ct.literal))),
+ mir::Operand::Constant(ct) => Ok(self.nodes.push(Node::Leaf(ct.literal))),
}
}
}
}
- fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Option<()> {
+ fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Result<(), ErrorReported> {
debug!("AbstractConstBuilder: stmt={:?}", stmt);
match stmt.kind {
StatementKind::Assign(box (ref place, ref rvalue)) => {
- let local = place.as_local()?;
+ let local = self.place_to_local(stmt.source_info.span, place)?;
match *rvalue {
Rvalue::Use(ref operand) => {
- self.locals[local] = self.operand_to_node(operand)?;
- Some(())
+ self.locals[local] =
+ self.operand_to_node(stmt.source_info.span, operand)?;
+ Ok(())
}
Rvalue::BinaryOp(op, ref lhs, ref rhs) if Self::check_binop(op) => {
- let lhs = self.operand_to_node(lhs)?;
- let rhs = self.operand_to_node(rhs)?;
+ let lhs = self.operand_to_node(stmt.source_info.span, lhs)?;
+ let rhs = self.operand_to_node(stmt.source_info.span, rhs)?;
self.locals[local] = self.nodes.push(Node::Binop(op, lhs, rhs));
if op.is_checkable() {
bug!("unexpected unchecked checkable binary operation");
} else {
- Some(())
+ Ok(())
}
}
Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) if Self::check_binop(op) => {
- let lhs = self.operand_to_node(lhs)?;
- let rhs = self.operand_to_node(rhs)?;
+ let lhs = self.operand_to_node(stmt.source_info.span, lhs)?;
+ let rhs = self.operand_to_node(stmt.source_info.span, rhs)?;
self.locals[local] = self.nodes.push(Node::Binop(op, lhs, rhs));
self.checked_op_locals.insert(local);
- Some(())
+ Ok(())
}
Rvalue::UnaryOp(op, ref operand) if Self::check_unop(op) => {
- let operand = self.operand_to_node(operand)?;
+ let operand = self.operand_to_node(stmt.source_info.span, operand)?;
self.locals[local] = self.nodes.push(Node::UnaryOp(op, operand));
- Some(())
+ Ok(())
}
- _ => None,
+ _ => self.error(Some(stmt.source_info.span), "unsupported rvalue")?,
}
}
// These are not actually relevant for us here, so we can ignore them.
- StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => Some(()),
- _ => None,
+ StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => Ok(()),
+ _ => self.error(Some(stmt.source_info.span), "unsupported statement")?,
}
}
fn build_terminator(
&mut self,
terminator: &mir::Terminator<'tcx>,
- ) -> Option<Option<mir::BasicBlock>> {
+ ) -> Result<Option<mir::BasicBlock>, ErrorReported> {
debug!("AbstractConstBuilder: terminator={:?}", terminator);
match terminator.kind {
- TerminatorKind::Goto { target } => Some(Some(target)),
- TerminatorKind::Return => Some(None),
+ TerminatorKind::Goto { target } => Ok(Some(target)),
+ TerminatorKind::Return => Ok(None),
TerminatorKind::Call {
ref func,
ref args,
//
// This is currently fairly irrelevant as it requires `const Trait`s.
from_hir_call: true,
- fn_span: _,
+ fn_span,
} => {
- let local = place.as_local()?;
- let func = self.operand_to_node(func)?;
+ let local = self.place_to_local(fn_span, place)?;
+ let func = self.operand_to_node(fn_span, func)?;
let args = self.tcx.arena.alloc_from_iter(
args.iter()
- .map(|arg| self.operand_to_node(arg))
- .collect::<Option<Vec<NodeId>>>()?,
+ .map(|arg| self.operand_to_node(terminator.source_info.span, arg))
+ .collect::<Result<Vec<NodeId>, _>>()?,
);
self.locals[local] = self.nodes.push(Node::FunctionCall(func, args));
- Some(Some(target))
+ Ok(Some(target))
}
// We only allow asserts for checked operations.
//
if let &[mir::ProjectionElem::Field(ONE_FIELD, _)] = p.projection.as_ref() {
// Only allow asserts checking the result of a checked operation.
if self.checked_op_locals.contains(p.local) {
- return Some(Some(target));
+ return Ok(Some(target));
}
}
- None
+ self.error(Some(terminator.source_info.span), "unsupported assertion")?;
}
- _ => None,
+ _ => self.error(Some(terminator.source_info.span), "unsupported terminator")?,
}
}
/// Builds the abstract const by walking the mir from start to finish
/// and bailing out when encountering an unsupported operation.
- fn build(mut self) -> Option<&'tcx [Node<'tcx>]> {
+ fn build(mut self) -> Result<&'tcx [Node<'tcx>], ErrorReported> {
let mut block = &self.body.basic_blocks()[mir::START_BLOCK];
// We checked for a cyclic cfg above, so this should terminate.
loop {
if let Some(next) = self.build_terminator(block.terminator())? {
block = &self.body.basic_blocks()[next];
} else {
- return Some(self.tcx.arena.alloc_from_iter(self.nodes));
+ return Ok(self.tcx.arena.alloc_from_iter(self.nodes));
}
}
}
pub(super) fn mir_abstract_const<'tcx>(
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
-) -> Option<&'tcx [Node<'tcx>]> {
+) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
if tcx.features().const_evaluatable_checked {
match tcx.def_kind(def.did) {
// FIXME(const_evaluatable_checked): We currently only do this for anonymous constants,
//
// Right now we do neither of that and simply always fail to unify them.
DefKind::AnonConst => (),
- _ => return None,
+ _ => return Ok(None),
}
let body = tcx.mir_const(def).borrow();
- AbstractConstBuilder::new(tcx, &body)?.build()
+ AbstractConstBuilder::new(tcx, &body)?.map(AbstractConstBuilder::build).transpose()
} else {
- None
+ Ok(None)
}
}
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
),
) -> bool {
- if let Some(a) = AbstractConst::new(tcx, a, a_substs) {
- if let Some(b) = AbstractConst::new(tcx, b, b_substs) {
- return try_unify(tcx, a, b);
+ (|| {
+ if let Some(a) = AbstractConst::new(tcx, a, a_substs)? {
+ if let Some(b) = AbstractConst::new(tcx, b, b_substs)? {
+ return Ok(try_unify(tcx, a, b));
+ }
}
- }
- false
+ Ok(false)
+ })()
+ .unwrap_or_else(|ErrorReported| true)
+ // FIXME(const_evaluatable_checked): We should instead have this
+ // method return the resulting `ty::Const` and return `ConstKind::Error`
+ // on `ErrorReported`.
}
/// Tries to unify two abstract constants using structural equality.
) {
let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
err.span_label(span, "cannot resolve opaque type");
- // Find the the owner that declared this `impl Trait` type.
+ // Find the owner that declared this `impl Trait` type.
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let mut prev_hir_id = hir_id;
let mut hir_id = tcx.hir().get_parent_node(hir_id);
impl Global {
#[inline]
- fn alloc_impl(&mut self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocErr> {
+ fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocErr> {
match layout.size() {
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)),
// SAFETY: `layout` is non-zero in size,
// SAFETY: Same as `AllocRef::grow`
#[inline]
unsafe fn grow_impl(
- &mut self,
+ &self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
#[unstable(feature = "allocator_api", issue = "32838")]
unsafe impl AllocRef for Global {
#[inline]
- fn alloc(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
+ fn alloc(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
self.alloc_impl(layout, false)
}
#[inline]
- fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
+ fn alloc_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
self.alloc_impl(layout, true)
}
#[inline]
- unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
+ unsafe fn dealloc(&self, ptr: NonNull<u8>, layout: Layout) {
if layout.size() != 0 {
// SAFETY: `layout` is non-zero in size,
// other conditions must be upheld by the caller
#[inline]
unsafe fn grow(
- &mut self,
+ &self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
#[inline]
unsafe fn grow_zeroed(
- &mut self,
+ &self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
#[inline]
unsafe fn shrink(
- &mut self,
+ &self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
Self::allocate_in(capacity, AllocInit::Zeroed, alloc)
}
- fn allocate_in(capacity: usize, init: AllocInit, mut alloc: A) -> Self {
+ fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self {
if mem::size_of::<T>() == 0 {
Self::new_in(alloc)
} else {
use super::*;
+use std::cell::Cell;
#[test]
fn allocator_param() {
// A dumb allocator that consumes a fixed amount of fuel
// before allocation attempts start failing.
struct BoundedAlloc {
- fuel: usize,
+ fuel: Cell<usize>,
}
unsafe impl AllocRef for BoundedAlloc {
- fn alloc(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
+ fn alloc(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
let size = layout.size();
- if size > self.fuel {
+ if size > self.fuel.get() {
return Err(AllocErr);
}
match Global.alloc(layout) {
ok @ Ok(_) => {
- self.fuel -= size;
+ self.fuel.set(self.fuel.get() - size);
ok
}
err @ Err(_) => err,
}
}
- unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
+ unsafe fn dealloc(&self, ptr: NonNull<u8>, layout: Layout) {
unsafe { Global.dealloc(ptr, layout) }
}
}
- let a = BoundedAlloc { fuel: 500 };
+ let a = BoundedAlloc { fuel: Cell::new(500) };
let mut v: RawVec<u8, _> = RawVec::with_capacity_in(50, a);
- assert_eq!(v.alloc.fuel, 450);
+ assert_eq!(v.alloc.fuel.get(), 450);
v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel)
- assert_eq!(v.alloc.fuel, 250);
+ assert_eq!(v.alloc.fuel.get(), 250);
}
#[test]
///
/// This `struct` is created by the `into_iter` method on [`Vec`] (provided
/// by the [`IntoIterator`] trait).
+///
+/// # Example
+///
+/// ```
+/// let v = vec![0, 1, 2];
+/// let iter: std::vec::IntoIter<_> = v.into_iter();
+/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<T> {
buf: NonNull<T>,
///
/// This `struct` is created by [`Vec::drain`].
/// See its documentation for more.
+///
+/// # Example
+///
+/// ```
+/// let mut v = vec![0, 1, 2];
+/// let iter: std::vec::Drain<_> = v.drain(..);
+/// ```
#[stable(feature = "drain", since = "1.6.0")]
pub struct Drain<'a, T: 'a> {
/// Index of tail to preserve
///
/// This struct is created by [`Vec::splice()`].
/// See its documentation for more.
+///
+/// # Example
+///
+/// ```
+/// let mut v = vec![0, 1, 2];
+/// let new = [7, 8];
+/// let iter: std::vec::Splice<_> = v.splice(1.., new.iter().cloned());
+/// ```
#[derive(Debug)]
#[stable(feature = "vec_splice", since = "1.21.0")]
pub struct Splice<'a, I: Iterator + 'a> {
///
/// This struct is created by [`Vec::drain_filter`].
/// See its documentation for more.
+///
+/// # Example
+///
+/// ```
+/// #![feature(drain_filter)]
+///
+/// let mut v = vec![0, 1, 2];
+/// let iter: std::vec::DrainFilter<_, _> = v.drain_filter(|x| *x % 2 == 0);
+/// ```
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
#[derive(Debug)]
pub struct DrainFilter<'a, T, F>
check_overalign_requests(Global)
}
-fn check_overalign_requests<T: AllocRef>(mut allocator: T) {
+fn check_overalign_requests<T: AllocRef>(allocator: T) {
for &align in &[4, 8, 16, 32] {
// less than and bigger than `MIN_ALIGN`
for &size in &[align / 2, align - 1] {
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
///
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
- fn alloc(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr>;
+ fn alloc(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr>;
/// Behaves like `alloc`, but also ensures that the returned memory is zero-initialized.
///
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
///
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
- fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
+ fn alloc_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
let ptr = self.alloc(layout)?;
// SAFETY: `alloc` returns a valid memory block
unsafe { ptr.as_non_null_ptr().as_ptr().write_bytes(0, ptr.len()) }
///
/// [*currently allocated*]: #currently-allocated-memory
/// [*fit*]: #memory-fitting
- unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout);
+ unsafe fn dealloc(&self, ptr: NonNull<u8>, layout: Layout);
/// Attempts to extend the memory block.
///
///
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
unsafe fn grow(
- &mut self,
+ &self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
///
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
unsafe fn grow_zeroed(
- &mut self,
+ &self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
///
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
unsafe fn shrink(
- &mut self,
+ &self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
///
/// The returned adaptor also implements `AllocRef` and will simply borrow this.
#[inline(always)]
- fn by_ref(&mut self) -> &mut Self {
+ fn by_ref(&mut self) -> &Self {
self
}
}
#[unstable(feature = "allocator_api", issue = "32838")]
-unsafe impl<A> AllocRef for &mut A
+unsafe impl<A> AllocRef for &A
where
A: AllocRef + ?Sized,
{
#[inline]
- fn alloc(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
+ fn alloc(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
(**self).alloc(layout)
}
#[inline]
- fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
+ fn alloc_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
(**self).alloc_zeroed(layout)
}
#[inline]
- unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
+ unsafe fn dealloc(&self, ptr: NonNull<u8>, layout: Layout) {
// SAFETY: the safety contract must be upheld by the caller
unsafe { (**self).dealloc(ptr, layout) }
}
#[inline]
unsafe fn grow(
- &mut self,
+ &self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
#[inline]
unsafe fn grow_zeroed(
- &mut self,
+ &self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
#[inline]
unsafe fn shrink(
- &mut self,
+ &self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
/// ```
#[inline]
#[stable(feature = "refcell_replace", since = "1.24.0")]
+ #[track_caller]
pub fn replace(&self, t: T) -> T {
mem::replace(&mut *self.borrow_mut(), t)
}
/// ```
#[inline]
#[stable(feature = "refcell_replace_swap", since = "1.35.0")]
+ #[track_caller]
pub fn replace_with<F: FnOnce(&mut T) -> T>(&self, f: F) -> T {
let mut_borrow = &mut *self.borrow_mut();
let replacement = f(mut_borrow);
///
/// Panics if the value is currently mutably borrowed.
#[inline]
+ #[track_caller]
fn clone(&self) -> RefCell<T> {
RefCell::new(self.borrow().clone())
}
unsafe { &mut *(self.v.get() as *mut bool) }
}
+ /// Get atomic access to a `&mut bool`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(atomic_from_mut)]
+ /// use std::sync::atomic::{AtomicBool, Ordering};
+ ///
+ /// let mut some_bool = true;
+ /// let a = AtomicBool::from_mut(&mut some_bool);
+ /// a.store(false, Ordering::Relaxed);
+ /// assert_eq!(some_bool, false);
+ /// ```
+ #[inline]
+ #[cfg(target_has_atomic_equal_alignment = "8")]
+ #[unstable(feature = "atomic_from_mut", issue = "76314")]
+ pub fn from_mut(v: &mut bool) -> &Self {
+ // SAFETY: the mutable reference guarantees unique ownership, and
+ // alignment of both `bool` and `Self` is 1.
+ unsafe { &*(v as *mut bool as *mut Self) }
+ }
+
/// Consumes the atomic and returns the contained value.
///
/// This is safe because passing `self` by value guarantees that no other threads are
self.p.get_mut()
}
+ /// Get atomic access to a pointer.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(atomic_from_mut)]
+ /// use std::sync::atomic::{AtomicPtr, Ordering};
+ ///
+ /// let mut some_ptr = &mut 123 as *mut i32;
+ /// let a = AtomicPtr::from_mut(&mut some_ptr);
+ /// a.store(&mut 456, Ordering::Relaxed);
+ /// assert_eq!(unsafe { *some_ptr }, 456);
+ /// ```
+ #[inline]
+ #[cfg(target_has_atomic_equal_alignment = "ptr")]
+ #[unstable(feature = "atomic_from_mut", issue = "76314")]
+ pub fn from_mut(v: &mut *mut T) -> &Self {
+ use crate::mem::align_of;
+ let [] = [(); align_of::<AtomicPtr<()>>() - align_of::<*mut ()>()];
+ // SAFETY:
+ // - the mutable reference guarantees unique ownership.
+ // - the alignment of `*mut T` and `Self` is the same on all platforms
+ // supported by rust, as verified above.
+ unsafe { &*(v as *mut *mut T as *mut Self) }
+ }
+
/// Consumes the atomic and returns the contained value.
///
/// This is safe because passing `self` by value guarantees that no other threads are
#[cfg(target_has_atomic_load_store = "8")]
macro_rules! atomic_int {
($cfg_cas:meta,
+ $cfg_align:meta,
$stable:meta,
$stable_cxchg:meta,
$stable_debug:meta,
}
}
+ doc_comment! {
+ concat!("Get atomic access to a `&mut ", stringify!($int_type), "`.
+
+",
+if_not_8_bit! {
+ $int_type,
+ concat!(
+ "**Note:** This function is only available on targets where `",
+ stringify!($int_type), "` has an alignment of ", $align, " bytes."
+ )
+},
+"
+
+# Examples
+
+```
+#![feature(atomic_from_mut)]
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let mut some_int = 123;
+let a = ", stringify!($atomic_type), "::from_mut(&mut some_int);
+a.store(100, Ordering::Relaxed);
+assert_eq!(some_int, 100);
+```
+ "),
+ #[inline]
+ #[$cfg_align]
+ #[unstable(feature = "atomic_from_mut", issue = "76314")]
+ pub fn from_mut(v: &mut $int_type) -> &Self {
+ use crate::mem::align_of;
+ let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
+ // SAFETY:
+ // - the mutable reference guarantees unique ownership.
+ // - the alignment of `$int_type` and `Self` is the
+ // same, as promised by $cfg_align and verified above.
+ unsafe { &*(v as *mut $int_type as *mut Self) }
+ }
+ }
+
doc_comment! {
concat!("Consumes the atomic and returns the contained value.
#[cfg(target_has_atomic_load_store = "8")]
atomic_int! {
cfg(target_has_atomic = "8"),
+ cfg(target_has_atomic_equal_alignment = "8"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
#[cfg(target_has_atomic_load_store = "8")]
atomic_int! {
cfg(target_has_atomic = "8"),
+ cfg(target_has_atomic_equal_alignment = "8"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
#[cfg(target_has_atomic_load_store = "16")]
atomic_int! {
cfg(target_has_atomic = "16"),
+ cfg(target_has_atomic_equal_alignment = "16"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
#[cfg(target_has_atomic_load_store = "16")]
atomic_int! {
cfg(target_has_atomic = "16"),
+ cfg(target_has_atomic_equal_alignment = "16"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
#[cfg(target_has_atomic_load_store = "32")]
atomic_int! {
cfg(target_has_atomic = "32"),
+ cfg(target_has_atomic_equal_alignment = "32"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
#[cfg(target_has_atomic_load_store = "32")]
atomic_int! {
cfg(target_has_atomic = "32"),
+ cfg(target_has_atomic_equal_alignment = "32"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
#[cfg(target_has_atomic_load_store = "64")]
atomic_int! {
cfg(target_has_atomic = "64"),
+ cfg(target_has_atomic_equal_alignment = "64"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
#[cfg(target_has_atomic_load_store = "64")]
atomic_int! {
cfg(target_has_atomic = "64"),
+ cfg(target_has_atomic_equal_alignment = "64"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
stable(feature = "integer_atomics_stable", since = "1.34.0"),
#[cfg(target_has_atomic_load_store = "128")]
atomic_int! {
cfg(target_has_atomic = "128"),
+ cfg(target_has_atomic_equal_alignment = "128"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
#[cfg(target_has_atomic_load_store = "128")]
atomic_int! {
cfg(target_has_atomic = "128"),
+ cfg(target_has_atomic_equal_alignment = "128"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
unstable(feature = "integer_atomics", issue = "32976"),
#[cfg(target_has_atomic_load_store = "ptr")]
atomic_int! {
cfg(target_has_atomic = "ptr"),
+ cfg(target_has_atomic_equal_alignment = "ptr"),
stable(feature = "rust1", since = "1.0.0"),
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
stable(feature = "atomic_debug", since = "1.3.0"),
#[cfg(target_has_atomic_load_store = "ptr")]
atomic_int! {
cfg(target_has_atomic = "ptr"),
+ cfg(target_has_atomic_equal_alignment = "ptr"),
stable(feature = "rust1", since = "1.0.0"),
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
stable(feature = "atomic_debug", since = "1.3.0"),
impl System {
#[inline]
- fn alloc_impl(&mut self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocErr> {
+ fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocErr> {
match layout.size() {
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)),
// SAFETY: `layout` is non-zero in size,
// SAFETY: Same as `AllocRef::grow`
#[inline]
unsafe fn grow_impl(
- &mut self,
+ &self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
old_size => unsafe {
let new_ptr = self.alloc_impl(new_layout, zeroed)?;
ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_size);
- self.dealloc(ptr, old_layout);
+ AllocRef::dealloc(&self, ptr, old_layout);
Ok(new_ptr)
},
}
#[unstable(feature = "allocator_api", issue = "32838")]
unsafe impl AllocRef for System {
#[inline]
- fn alloc(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
+ fn alloc(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
self.alloc_impl(layout, false)
}
#[inline]
- fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
+ fn alloc_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
self.alloc_impl(layout, true)
}
#[inline]
- unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
+ unsafe fn dealloc(&self, ptr: NonNull<u8>, layout: Layout) {
if layout.size() != 0 {
// SAFETY: `layout` is non-zero in size,
// other conditions must be upheld by the caller
#[inline]
unsafe fn grow(
- &mut self,
+ &self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
#[inline]
unsafe fn grow_zeroed(
- &mut self,
+ &self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
#[inline]
unsafe fn shrink(
- &mut self,
+ &self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
match new_layout.size() {
// SAFETY: conditions must be upheld by the caller
0 => unsafe {
- self.dealloc(ptr, old_layout);
+ AllocRef::dealloc(&self, ptr, old_layout);
Ok(NonNull::slice_from_raw_parts(new_layout.dangling(), 0))
},
// `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract
// for `dealloc` must be upheld by the caller.
new_size => unsafe {
- let new_ptr = self.alloc(new_layout)?;
+ let new_ptr = AllocRef::alloc(&self, new_layout)?;
ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), new_size);
- self.dealloc(ptr, old_layout);
+ AllocRef::dealloc(&self, ptr, old_layout);
Ok(new_ptr)
},
}
/// `(`[`Ipv4Addr`]`, `[`u16`]`)`, `(`[`Ipv6Addr`]`, `[`u16`]`)`:
/// [`to_socket_addrs`] constructs a [`SocketAddr`] trivially.
///
-/// * `(`[`&str`]`, `[`u16`]`)`: the string should be either a string representation
+/// * `(`[`&str`]`, `[`u16`]`)`: [`&str`] should be either a string representation
/// of an [`IpAddr`] address as expected by [`FromStr`] implementation or a host
-/// name.
+/// name. [`u16`] is the port number.
///
/// * [`&str`]: the string should be either a string representation of a
/// [`SocketAddr`] as expected by its [`FromStr`] implementation or a string like
use std::alloc::{self, AllocRef, Global, Layout, System};
use std::sync::atomic::{AtomicUsize, Ordering};
+use std::ptr::NonNull;
static HITS: AtomicUsize = AtomicUsize::new(0);
unsafe impl alloc::GlobalAlloc for A {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
HITS.fetch_add(1, Ordering::SeqCst);
- System.alloc(layout)
+ alloc::GlobalAlloc::alloc(&System, layout)
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
HITS.fetch_add(1, Ordering::SeqCst);
- System.dealloc(ptr, layout)
+ AllocRef::dealloc(&System, NonNull::new(ptr).unwrap(), layout)
}
}
--- /dev/null
+// only-x86
+// only-linux
+
+fn main() {
+ core::sync::atomic::AtomicU64::from_mut(&mut 0u64);
+ //~^ ERROR: no function or associated item named `from_mut` found for struct `AtomicU64`
+}
--- /dev/null
+error[E0599]: no function or associated item named `from_mut` found for struct `AtomicU64` in the current scope
+ --> $DIR/atomic-from-mut-not-available.rs:5:36
+ |
+LL | core::sync::atomic::AtomicU64::from_mut(&mut 0u64);
+ | ^^^^^^^^ function or associated item not found in `AtomicU64`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
--- /dev/null
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
+//~^ ERROR overly complex generic constant
+
+fn main() {}
--- /dev/null
+error: overly complex generic constant
+ --> $DIR/closures.rs:3:35
+ |
+LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
+ | ^^^^-------^^
+ | |
+ | unsupported rvalue
+ |
+ = help: consider moving this anonymous constant into a `const` function
+
+error: aborting due to previous error
+
// We do not yet want to support let-bindings in abstract consts,
// so this test should keep failing for now.
fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
- //~^ ERROR constant expression depends
- //~| ERROR constant expression depends
+ //~^ ERROR overly complex generic constant
+ //~| ERROR overly complex generic constant
Default::default()
}
-error: constant expression depends on a generic parameter
- --> $DIR/let-bindings.rs:6:91
+error: overly complex generic constant
+ --> $DIR/let-bindings.rs:6:68
|
LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
- | ^^^^^^^ required by this bound in `test::{{constant}}#0`
+ | ^^^^^^-^^^^^^^^^^^^^
+ | |
+ | unsupported statement
|
- = note: this may fail depending on what value the parameter takes
+ = help: consider moving this anonymous constant into a `const` function
-error: constant expression depends on a generic parameter
- --> $DIR/let-bindings.rs:6:30
+error: overly complex generic constant
+ --> $DIR/let-bindings.rs:6:35
|
LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^-^^^^^^^^^^^^^
+ | |
+ | unsupported statement
|
- = note: this may fail depending on what value the parameter takes
+ = help: consider moving this anonymous constant into a `const` function
error: aborting due to 2 previous errors
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
-LL | / pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-LL | | // Code here does not matter - this is replaced by the
-LL | | // real drop glue by the compiler.
-LL | |
-LL | | // SAFETY: see comment above
-LL | | unsafe { drop_in_place(to_drop) }
-LL | | }
- | | ^
- | | |
- | |_calling non-const function `<Vec<i32> as Drop>::drop`
- | inside `drop_in_place::<Vec<i32>> - shim(Some(Vec<i32>))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | calling non-const function `<Vec<i32> as Drop>::drop`
+ | inside `drop_in_place::<Vec<i32>> - shim(Some(Vec<i32>))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
::: $DIR/drop.rs:18:1
|
-LL | };
- | - inside `TEST_BAD` at $DIR/drop.rs:18:1
+LL | };
+ | - inside `TEST_BAD` at $DIR/drop.rs:18:1
warning: skipping const checks
|
//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
cfg!(target_has_atomic = "ptr");
//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
+ cfg!(target_has_atomic_load_store = "8");
+ //~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
+ cfg!(target_has_atomic_load_store = "16");
+ //~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
+ cfg!(target_has_atomic_load_store = "32");
+ //~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
+ cfg!(target_has_atomic_load_store = "64");
+ //~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
+ cfg!(target_has_atomic_load_store = "128");
+ //~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
+ cfg!(target_has_atomic_load_store = "ptr");
+ //~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change
+ cfg!(target_has_atomic_equal_alignment = "8");
+ //~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
+ cfg!(target_has_atomic_equal_alignment = "16");
+ //~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
+ cfg!(target_has_atomic_equal_alignment = "32");
+ //~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
+ cfg!(target_has_atomic_equal_alignment = "64");
+ //~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
+ cfg!(target_has_atomic_equal_alignment = "128");
+ //~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
+ cfg!(target_has_atomic_equal_alignment = "ptr");
+ //~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
}
#[macro_export]
= note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
= help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable
-error: aborting due to 18 previous errors
+error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change
+ --> $DIR/feature-gate-cfg-target-has-atomic.rs:90:10
+ |
+LL | cfg!(target_has_atomic_load_store = "8");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
+ = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change
+ --> $DIR/feature-gate-cfg-target-has-atomic.rs:92:10
+ |
+LL | cfg!(target_has_atomic_load_store = "16");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
+ = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change
+ --> $DIR/feature-gate-cfg-target-has-atomic.rs:94:10
+ |
+LL | cfg!(target_has_atomic_load_store = "32");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
+ = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change
+ --> $DIR/feature-gate-cfg-target-has-atomic.rs:96:10
+ |
+LL | cfg!(target_has_atomic_load_store = "64");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
+ = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change
+ --> $DIR/feature-gate-cfg-target-has-atomic.rs:98:10
+ |
+LL | cfg!(target_has_atomic_load_store = "128");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
+ = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change
+ --> $DIR/feature-gate-cfg-target-has-atomic.rs:100:10
+ |
+LL | cfg!(target_has_atomic_load_store = "ptr");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
+ = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
+ --> $DIR/feature-gate-cfg-target-has-atomic.rs:102:10
+ |
+LL | cfg!(target_has_atomic_equal_alignment = "8");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
+ = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
+ --> $DIR/feature-gate-cfg-target-has-atomic.rs:104:10
+ |
+LL | cfg!(target_has_atomic_equal_alignment = "16");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
+ = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
+ --> $DIR/feature-gate-cfg-target-has-atomic.rs:106:10
+ |
+LL | cfg!(target_has_atomic_equal_alignment = "32");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
+ = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
+ --> $DIR/feature-gate-cfg-target-has-atomic.rs:108:10
+ |
+LL | cfg!(target_has_atomic_equal_alignment = "64");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
+ = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
+ --> $DIR/feature-gate-cfg-target-has-atomic.rs:110:10
+ |
+LL | cfg!(target_has_atomic_equal_alignment = "128");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
+ = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable
+
+error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change
+ --> $DIR/feature-gate-cfg-target-has-atomic.rs:112:10
+ |
+LL | cfg!(target_has_atomic_equal_alignment = "ptr");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #32976 <https://github.com/rust-lang/rust/issues/32976> for more information
+ = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable
+
+error: aborting due to 30 previous errors
For more information about this error, try `rustc --explain E0658`.
error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments
--> $DIR/same-sequence-span.rs:19:1
|
-LL | proc_macro_sequence::make_foo!();
- | ^--------------------------------
- | |
- | _in this macro invocation
+LL | proc_macro_sequence::make_foo!();
+ | ---------------------------------^^^^^^^^^^^^^
| |
-LL | |
-LL | |
-LL | | fn main() {}
-... |
+ | not allowed after `expr` fragments
+ | in this macro invocation
|
= note: allowed there are: `=>`, `,` or `;`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-Def site: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#5)
+Def site: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5)
Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:24:37: 24:43 (#4) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:24:43: 24:45 (#4) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:43: 24:45 (#4) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:24:45: 24:50 (#4) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:50: 24:51 (#4) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:24:51: 24:53 (#4) }]
-Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#5) }, Punct { ch: ':', spacing: Joint, span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#5) }, Punct { ch: ':', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#5) }, Ident { ident: "dummy", span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#5) }, Punct { ch: '!', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#5) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#5) }]
+Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: ':', spacing: Joint, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: ':', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Ident { ident: "dummy", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: '!', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }]
#![feature /* 0#0 */(prelude_import)]
// ignore-tidy-linelength
// aux-build:make-macro.rs
-Def site: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#4)
+Def site: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4)
Input: TokenStream []
Respanned: TokenStream []
error: reached the recursion limit while instantiating `drop_in_place::<S<fn(fn(fn(fn(fn...)))))))))))))))))))))))))))))>))`
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
-LL | / pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-LL | | // Code here does not matter - this is replaced by the
-LL | | // real drop glue by the compiler.
-LL | |
-LL | | // SAFETY: see comment above
-LL | | unsafe { drop_in_place(to_drop) }
-LL | | }
- | |_^
+LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `drop_in_place` defined here
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
-LL | / pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-LL | | // Code here does not matter - this is replaced by the
-LL | | // real drop glue by the compiler.
-LL | |
-LL | | // SAFETY: see comment above
-LL | | unsafe { drop_in_place(to_drop) }
-LL | | }
- | |_^
+LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-38591-non-regular-dropck-recursion/issue-38591-non-regular-dropck-recursion.long-type.txt'
error: aborting due to previous error
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
LL | pub fn drop<T>(_x: T) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
|
= note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
= help: consider adding a `#![type_length_limit="8"]` attribute to your crate