Auto merge of #77102 - Dylan-DPC:rollup-2jfrg3u, r=Dylan-DPC
Rollup of 9 pull requests Successful merges: - #76898 (Record `tcx.def_span` instead of `item.span` in crate metadata) - #76939 (emit errors during AbstractConst building) - #76965 (Add cfg(target_has_atomic_equal_alignment) and use it for Atomic::from_mut.) - #76993 (Changing the alloc() to accept &self instead of &mut self) - #76994 (fix small typo in docs and comments) - #77017 (Add missing examples on Vec iter types) - #77042 (Improve documentation for ToSocketAddrs) - #77047 (Miri: more informative deallocation error messages) - #77055 (Add #[track_caller] to more panicking Cell functions) Failed merges: r? `@ghost`
This commit is contained in:
commit
c35177582b
@ -26,6 +26,11 @@ const GATED_CFGS: &[GatedCfg] = &[
|
||||
(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)),
|
||||
];
|
||||
|
@ -733,7 +733,7 @@ fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'t
|
||||
}
|
||||
|
||||
/// 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.
|
||||
|
@ -11,6 +11,7 @@ use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder};
|
||||
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;
|
||||
@ -1201,13 +1202,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
&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> {
|
||||
|
@ -1117,7 +1117,7 @@ impl EncodeContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -1300,7 +1300,7 @@ impl EncodeContext<'a, 'tcx> {
|
||||
});
|
||||
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 {
|
||||
|
@ -23,6 +23,12 @@ pub enum ErrorHandled {
|
||||
TooGeneric,
|
||||
}
|
||||
|
||||
impl From<ErrorReported> for ErrorHandled {
|
||||
fn from(err: ErrorReported) -> ErrorHandled {
|
||||
ErrorHandled::Reported(err)
|
||||
}
|
||||
}
|
||||
|
||||
CloneTypeFoldableAndLiftImpls! {
|
||||
ErrorHandled,
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ impl PredecessorCache {
|
||||
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,
|
||||
|
@ -247,7 +247,7 @@ rustc_queries! {
|
||||
/// 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),
|
||||
}
|
||||
@ -255,7 +255,7 @@ rustc_queries! {
|
||||
/// 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 {}",
|
||||
|
@ -71,7 +71,7 @@ impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> {
|
||||
/// 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
|
||||
|
@ -285,9 +285,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
||||
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)),
|
||||
}
|
||||
@ -297,7 +299,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
||||
|
||||
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
|
||||
);
|
||||
@ -305,7 +308,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
||||
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(),
|
||||
|
@ -321,7 +321,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
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,
|
||||
|
@ -67,7 +67,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
/// 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)
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ use rustc_data_structures::fx::FxHashSet;
|
||||
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;
|
||||
@ -748,6 +749,9 @@ pub fn default_configuration(sess: &Session) -> 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
|
||||
@ -769,18 +773,27 @@ pub fn default_configuration(sess: &Session) -> CrateConfig {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ symbols! {
|
||||
// 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
|
||||
@ -1071,6 +1071,7 @@ symbols! {
|
||||
target_feature,
|
||||
target_feature_11,
|
||||
target_has_atomic,
|
||||
target_has_atomic_equal_alignment,
|
||||
target_has_atomic_load_store,
|
||||
target_os,
|
||||
target_pointer_width,
|
||||
|
@ -30,7 +30,7 @@
|
||||
//! ## 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
|
||||
|
@ -15,6 +15,7 @@
|
||||
#![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
|
||||
|
@ -8,6 +8,7 @@
|
||||
//! 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;
|
||||
@ -31,7 +32,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||
) -> 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) => {
|
||||
@ -39,7 +40,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||
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");
|
||||
@ -114,7 +115,7 @@ impl AbstractConst<'tcx> {
|
||||
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))?
|
||||
@ -122,7 +123,7 @@ impl AbstractConst<'tcx> {
|
||||
_ => tcx.mir_abstract_const(def.did)?,
|
||||
};
|
||||
|
||||
Some(AbstractConst { inner, substs })
|
||||
Ok(inner.map(|inner| AbstractConst { inner, substs }))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -148,53 +149,83 @@ struct AbstractConstBuilder<'a, 'tcx> {
|
||||
}
|
||||
|
||||
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))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,44 +248,45 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
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")?,
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,11 +298,11 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||
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,
|
||||
@ -288,17 +320,17 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
@ -315,19 +347,19 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||
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 {
|
||||
@ -339,7 +371,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -349,7 +381,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||
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,
|
||||
@ -358,12 +390,12 @@ pub(super) fn mir_abstract_const<'tcx>(
|
||||
//
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -374,13 +406,19 @@ pub(super) fn try_unify_abstract_consts<'tcx>(
|
||||
(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.
|
||||
|
@ -672,7 +672,7 @@ fn binding_opaque_type_cycle_error(
|
||||
) {
|
||||
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);
|
||||
|
@ -145,7 +145,7 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
|
||||
|
||||
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,
|
||||
@ -160,7 +160,7 @@ impl Global {
|
||||
// SAFETY: Same as `AllocRef::grow`
|
||||
#[inline]
|
||||
unsafe fn grow_impl(
|
||||
&mut self,
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
@ -208,17 +208,17 @@ impl Global {
|
||||
#[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
|
||||
@ -228,7 +228,7 @@ unsafe impl AllocRef for Global {
|
||||
|
||||
#[inline]
|
||||
unsafe fn grow(
|
||||
&mut self,
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
@ -239,7 +239,7 @@ unsafe impl AllocRef for Global {
|
||||
|
||||
#[inline]
|
||||
unsafe fn grow_zeroed(
|
||||
&mut self,
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
@ -250,7 +250,7 @@ unsafe impl AllocRef for Global {
|
||||
|
||||
#[inline]
|
||||
unsafe fn shrink(
|
||||
&mut self,
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
|
@ -170,7 +170,7 @@ impl<T, A: AllocRef> RawVec<T, A> {
|
||||
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 {
|
||||
|
@ -1,4 +1,5 @@
|
||||
use super::*;
|
||||
use std::cell::Cell;
|
||||
|
||||
#[test]
|
||||
fn allocator_param() {
|
||||
@ -17,32 +18,32 @@ 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]
|
||||
|
@ -2849,6 +2849,13 @@ where
|
||||
///
|
||||
/// 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>,
|
||||
@ -3092,6 +3099,13 @@ impl<T> AsIntoIter for IntoIter<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
|
||||
@ -3221,6 +3235,14 @@ impl<T> FusedIterator for Drain<'_, T> {}
|
||||
///
|
||||
/// 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> {
|
||||
@ -3337,6 +3359,15 @@ impl<T> Drain<'_, T> {
|
||||
///
|
||||
/// 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>
|
||||
|
@ -11,7 +11,7 @@ fn std_heap_overaligned_request() {
|
||||
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] {
|
||||
|
@ -109,7 +109,7 @@ pub unsafe trait AllocRef {
|
||||
/// 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.
|
||||
///
|
||||
@ -126,7 +126,7 @@ pub unsafe trait AllocRef {
|
||||
/// 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()) }
|
||||
@ -142,7 +142,7 @@ pub unsafe trait AllocRef {
|
||||
///
|
||||
/// [*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.
|
||||
///
|
||||
@ -183,7 +183,7 @@ pub unsafe trait AllocRef {
|
||||
///
|
||||
/// [`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,
|
||||
@ -244,7 +244,7 @@ pub unsafe trait AllocRef {
|
||||
///
|
||||
/// [`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,
|
||||
@ -308,7 +308,7 @@ pub unsafe trait AllocRef {
|
||||
///
|
||||
/// [`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,
|
||||
@ -337,35 +337,35 @@ pub unsafe trait AllocRef {
|
||||
///
|
||||
/// 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,
|
||||
@ -376,7 +376,7 @@ where
|
||||
|
||||
#[inline]
|
||||
unsafe fn grow_zeroed(
|
||||
&mut self,
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
@ -387,7 +387,7 @@ where
|
||||
|
||||
#[inline]
|
||||
unsafe fn shrink(
|
||||
&mut self,
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
|
@ -697,6 +697,7 @@ impl<T> RefCell<T> {
|
||||
/// ```
|
||||
#[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)
|
||||
}
|
||||
@ -719,6 +720,7 @@ impl<T> RefCell<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);
|
||||
@ -1052,6 +1054,7 @@ impl<T: Clone> Clone for RefCell<T> {
|
||||
///
|
||||
/// Panics if the value is currently mutably borrowed.
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
fn clone(&self) -> RefCell<T> {
|
||||
RefCell::new(self.borrow().clone())
|
||||
}
|
||||
|
@ -327,6 +327,28 @@ impl AtomicBool {
|
||||
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
|
||||
@ -819,6 +841,32 @@ impl<T> AtomicPtr<T> {
|
||||
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
|
||||
@ -1113,6 +1161,7 @@ macro_rules! if_not_8_bit {
|
||||
#[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,
|
||||
@ -1231,6 +1280,45 @@ assert_eq!(some_var.load(Ordering::SeqCst), 5);
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
@ -1873,6 +1961,7 @@ let mut atomic = ", stringify!($atomic_type), "::new(1);
|
||||
#[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"),
|
||||
@ -1891,6 +1980,7 @@ atomic_int! {
|
||||
#[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"),
|
||||
@ -1909,6 +1999,7 @@ atomic_int! {
|
||||
#[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"),
|
||||
@ -1927,6 +2018,7 @@ atomic_int! {
|
||||
#[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"),
|
||||
@ -1945,6 +2037,7 @@ atomic_int! {
|
||||
#[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"),
|
||||
@ -1963,6 +2056,7 @@ atomic_int! {
|
||||
#[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"),
|
||||
@ -1981,6 +2075,7 @@ atomic_int! {
|
||||
#[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"),
|
||||
@ -1999,6 +2094,7 @@ atomic_int! {
|
||||
#[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"),
|
||||
@ -2017,6 +2113,7 @@ atomic_int! {
|
||||
#[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"),
|
||||
@ -2035,6 +2132,7 @@ atomic_int! {
|
||||
#[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"),
|
||||
@ -2074,6 +2172,7 @@ macro_rules! ptr_width {
|
||||
#[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"),
|
||||
@ -2092,6 +2191,7 @@ atomic_int! {
|
||||
#[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"),
|
||||
|
@ -133,7 +133,7 @@ pub struct System;
|
||||
|
||||
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,
|
||||
@ -152,7 +152,7 @@ impl System {
|
||||
// SAFETY: Same as `AllocRef::grow`
|
||||
#[inline]
|
||||
unsafe fn grow_impl(
|
||||
&mut self,
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
@ -190,7 +190,7 @@ impl System {
|
||||
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)
|
||||
},
|
||||
}
|
||||
@ -202,17 +202,17 @@ impl System {
|
||||
#[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
|
||||
@ -222,7 +222,7 @@ unsafe impl AllocRef for System {
|
||||
|
||||
#[inline]
|
||||
unsafe fn grow(
|
||||
&mut self,
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
@ -233,7 +233,7 @@ unsafe impl AllocRef for System {
|
||||
|
||||
#[inline]
|
||||
unsafe fn grow_zeroed(
|
||||
&mut self,
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
@ -244,7 +244,7 @@ unsafe impl AllocRef for System {
|
||||
|
||||
#[inline]
|
||||
unsafe fn shrink(
|
||||
&mut self,
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
@ -257,7 +257,7 @@ unsafe impl AllocRef for System {
|
||||
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))
|
||||
},
|
||||
|
||||
@ -277,9 +277,9 @@ unsafe impl AllocRef for System {
|
||||
// `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)
|
||||
},
|
||||
}
|
||||
|
@ -745,9 +745,9 @@ impl hash::Hash for SocketAddrV6 {
|
||||
/// `(`[`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
|
||||
|
@ -10,6 +10,7 @@ extern crate helper;
|
||||
|
||||
use std::alloc::{self, AllocRef, Global, Layout, System};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
static HITS: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
@ -18,12 +19,12 @@ struct A;
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
7
src/test/ui/atomic-from-mut-not-available.rs
Normal file
7
src/test/ui/atomic-from-mut-not-available.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// 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`
|
||||
}
|
9
src/test/ui/atomic-from-mut-not-available.stderr
Normal file
9
src/test/ui/atomic-from-mut-not-available.stderr
Normal file
@ -0,0 +1,9 @@
|
||||
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`.
|
@ -0,0 +1,6 @@
|
||||
#![feature(const_generics, const_evaluatable_checked)]
|
||||
#![allow(incomplete_features)]
|
||||
fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
|
||||
//~^ ERROR overly complex generic constant
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,12 @@
|
||||
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
|
||||
|
@ -4,8 +4,8 @@
|
||||
// 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()
|
||||
}
|
||||
|
||||
|
@ -1,18 +1,22 @@
|
||||
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
|
||||
|
||||
|
@ -1,22 +1,16 @@
|
||||
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
|
||||
|
|
||||
|
@ -87,6 +87,30 @@ fn main() {
|
||||
//~^ 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]
|
||||
|
@ -160,6 +160,114 @@ LL | cfg!(target_has_atomic = "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 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`.
|
||||
|
@ -17,15 +17,11 @@ LL | $(= $z:tt)*
|
||||
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)
|
||||
|
@ -1,6 +1,6 @@
|
||||
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
|
||||
|
@ -1,3 +1,3 @@
|
||||
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 []
|
||||
|
@ -1,26 +1,14 @@
|
||||
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
|
||||
|
@ -2,7 +2,7 @@ error: reached the type-length limit while instantiating `std::mem::drop::<Optio
|
||||
--> $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
|
||||
|
Loading…
Reference in New Issue
Block a user