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:
bors 2020-09-23 22:34:44 +00:00
commit c35177582b
42 changed files with 552 additions and 199 deletions

View File

@ -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)),
];

View File

@ -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.

View File

@ -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> {

View File

@ -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 {

View File

@ -23,6 +23,12 @@ pub enum ErrorHandled {
TooGeneric,
}
impl From<ErrorReported> for ErrorHandled {
fn from(err: ErrorReported) -> ErrorHandled {
ErrorHandled::Reported(err)
}
}
CloneTypeFoldableAndLiftImpls! {
ErrorHandled,
}

View File

@ -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,

View File

@ -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 {}",

View File

@ -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

View File

@ -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(),

View File

@ -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,

View File

@ -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)
}

View File

@ -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);
}
}
}

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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);

View File

@ -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,

View File

@ -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 {

View File

@ -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]

View File

@ -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>

View File

@ -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] {

View File

@ -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,

View File

@ -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())
}

View File

@ -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"),

View File

@ -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)
},
}

View File

@ -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

View File

@ -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)
}
}

View 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`
}

View 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`.

View File

@ -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() {}

View File

@ -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

View File

@ -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()
}

View File

@ -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

View File

@ -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
|

View File

@ -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]

View File

@ -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`.

View File

@ -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)

View File

@ -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

View File

@ -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 []

View File

@ -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

View File

@ -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