]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #77102 - Dylan-DPC:rollup-2jfrg3u, r=Dylan-DPC
authorbors <bors@rust-lang.org>
Wed, 23 Sep 2020 22:34:44 +0000 (22:34 +0000)
committerbors <bors@rust-lang.org>
Wed, 23 Sep 2020 22:34:44 +0000 (22:34 +0000)
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`

42 files changed:
compiler/rustc_feature/src/builtin_attrs.rs
compiler/rustc_lint/src/types.rs
compiler/rustc_metadata/src/rmeta/decoder.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_middle/src/mir/interpret/error.rs
compiler/rustc_middle/src/mir/predecessors.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_mir/src/borrow_check/member_constraints.rs
compiler/rustc_mir/src/interpret/memory.rs
compiler/rustc_mir_build/src/build/matches/mod.rs
compiler/rustc_parse/src/parser/ty.rs
compiler/rustc_session/src/config.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_target/src/spec/wasm32_wasi.rs
compiler/rustc_trait_selection/src/lib.rs
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
compiler/rustc_typeck/src/check/mod.rs
library/alloc/src/alloc.rs
library/alloc/src/raw_vec.rs
library/alloc/src/raw_vec/tests.rs
library/alloc/src/vec.rs
library/alloc/tests/heap.rs
library/core/src/alloc/mod.rs
library/core/src/cell.rs
library/core/src/sync/atomic.rs
library/std/src/alloc.rs
library/std/src/net/addr.rs
src/test/ui/allocator/custom.rs
src/test/ui/atomic-from-mut-not-available.rs [new file with mode: 0644]
src/test/ui/atomic-from-mut-not-available.stderr [new file with mode: 0644]
src/test/ui/const-generics/const_evaluatable_checked/closures.rs [new file with mode: 0644]
src/test/ui/const-generics/const_evaluatable_checked/closures.stderr [new file with mode: 0644]
src/test/ui/const-generics/const_evaluatable_checked/let-bindings.rs
src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr
src/test/ui/consts/miri_unleashed/drop.stderr
src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs
src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr
src/test/ui/macros/same-sequence-span.stderr
src/test/ui/proc-macro/meta-macro-hygiene.stdout
src/test/ui/proc-macro/meta-macro.stdout
src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
src/test/ui/type_length_limit.stderr

index fc122db8ac1b1f2502c2079bdf10e6c3fe53ea17..8b7fd59cd874ae57c665d559af0de011bad64126 100644 (file)
@@ -26,6 +26,11 @@ macro_rules! cfg_fn {
     (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)),
 ];
index ccbe9f80e25b73a3b086644c696727b2d76779b5..6aa28d04ae197ff5ca3a1a7ed2a9c3816e719865 100644 (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.
index a2e2cf1ca0219b947a8979ad2947be8363448c3b..72d54a26b01d4469350c351559bb5f3f2757aadf 100644 (file)
@@ -11,6 +11,7 @@
 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 @@ fn get_mir_abstract_const(
         &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> {
index eb091d86b82c6d3ddd84d01ce5e84358254c2b76..556cf419920769015c2c545b93777cd8c5062b4e 100644 (file)
@@ -1117,7 +1117,7 @@ fn encode_optimized_mir(&mut self, def_id: LocalDefId) {
             }
 
             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 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'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 {
index 13333dc45de0c4bbac2b16ce930c590095ee5644..d41e5680602194c30fc939bd7ae1c9daba845ec9 100644 (file)
@@ -23,6 +23,12 @@ pub enum ErrorHandled {
     TooGeneric,
 }
 
+impl From<ErrorReported> for ErrorHandled {
+    fn from(err: ErrorReported) -> ErrorHandled {
+        ErrorHandled::Reported(err)
+    }
+}
+
 CloneTypeFoldableAndLiftImpls! {
     ErrorHandled,
 }
index b16a1d53fff1cdb2ea5e4f29bcad58e1d9becc1f..a8b748833556d8e87df876add7b8bf7d4c8d39e5 100644 (file)
@@ -33,7 +33,7 @@ pub(super) fn invalidate(&mut self) {
         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,
index c0a606a586b6b5b549a458584b5f5512f88d3085..33854432af5a094237493239e999f2fc290cefd7 100644 (file)
@@ -247,7 +247,7 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
         /// 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 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
         /// 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 {}",
index d4baa5d809a22eb774e51049eae8f398e2fc761f..baaf6f27ee821377069a336a1e6532723b16d209 100644 (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
index 86e242c67d520439172fba2032f913b4ef920fe5..f3e373813ca537c3e40bcccb63b2410f254bcea1 100644 (file)
@@ -285,9 +285,11 @@ pub fn deallocate(
             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 @@ pub fn deallocate(
 
         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 @@ pub fn deallocate(
         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(),
index 6e9d5eedf051f231c732b2bfd0f8c3686093e90f..a9b8a6181d499b443221e99e84c435cb53b2fe66 100644 (file)
@@ -321,7 +321,7 @@ fn bind_pattern(
             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,
index fc4c62ccbd90e7b4865827d2bc3997b2360ce012..d42a786a18fe9cfcebd1ffd59f20d195312b8620 100644 (file)
@@ -67,7 +67,7 @@ pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
 
     /// 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)
     }
index 8d004675d7f4dd69aaa4196e4083fb80821e3150..ab96b0333f43fd3617dd0617e9962c7b8ca62779 100644 (file)
@@ -12,6 +12,7 @@
 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);
             }
         }
     }
index 6085eedf23694404fbf1a12ff1fb378a221c7eb7..2d5c6451d1a52d59a421d46a6530da9dafde364c 100644 (file)
     // called `sym::proc_macro` because then it's easy to mistakenly think it
     // represents "proc_macro".
     //
-    // As well as the symbols listed, there are symbols for the the strings
+    // As well as the symbols listed, there are symbols for the strings
     // "0", "1", ..., "9", which are accessible via `sym::integer`.
     //
     // The proc macro will abort if symbols are not in alphabetical order (as
         target_feature,
         target_feature_11,
         target_has_atomic,
+        target_has_atomic_equal_alignment,
         target_has_atomic_load_store,
         target_os,
         target_pointer_width,
index 0bba7bdd4735cbc53f62b65ef3a624fb89e2a62f..351167105ec7a689350c41656d991d6033069497 100644 (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
index da1996b92a60b520f4fab62e38031a9f3bc266f9..a53075448eddc5980b20dc1ac9331ff94b71b357 100644 (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
index 2642358dbc54c4a6b99b7f9ce6d47766bda88fea..0cfcaca9060336f2140a0e24d7f6e7647518047b 100644 (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 @@ pub fn new(
         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 @@ pub fn new(
             _ => 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 @@ fn check_unop(op: mir::UnOp) -> bool {
         }
     }
 
-    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 @@ fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Option<()> {
     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 @@ fn build_terminator(
                 //
                 // 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 @@ fn build_terminator(
                 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 @@ fn build(mut self) -> Option<&'tcx [Node<'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 @@ fn build(mut self) -> Option<&'tcx [Node<'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.
index 04d4d8171d48aef857dec6f97e4732ca7260d462..97172d391ba659a71f4f84e3c2b6a311bd8c3468 100644 (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);
index 341c6816197c7bf7161e228c76283471ba126228..8b8cdbf252555089b8e1f0db64b367afa1d2240f 100644 (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 @@ fn alloc_impl(&mut self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>,
     // 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 @@ unsafe fn grow_impl(
 #[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 fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
 
     #[inline]
     unsafe fn grow(
-        &mut self,
+        &self,
         ptr: NonNull<u8>,
         old_layout: Layout,
         new_layout: Layout,
@@ -239,7 +239,7 @@ unsafe fn grow(
 
     #[inline]
     unsafe fn grow_zeroed(
-        &mut self,
+        &self,
         ptr: NonNull<u8>,
         old_layout: Layout,
         new_layout: Layout,
@@ -250,7 +250,7 @@ unsafe fn grow_zeroed(
 
     #[inline]
     unsafe fn shrink(
-        &mut self,
+        &self,
         ptr: NonNull<u8>,
         old_layout: Layout,
         new_layout: Layout,
index e6da599006000dbdeef4f570fc993cab3d45372d..1844d3ae004f4dbbbbad92543d19367a8da1ad39 100644 (file)
@@ -170,7 +170,7 @@ pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self {
         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 {
index cadd913aa6bf244f1f6e9bc530dd069dcc002a36..e4c8b3709dfeeb9809d998747a40625579ba1038 100644 (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]
index 8c0b6af54829b4cbfc1a224bbd51b94cfd03fc20..8a9463cb518280934ffc2ab75ebac7b31bf66ff8 100644 (file)
@@ -2849,6 +2849,13 @@ fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Cow<'a, [T]> {
 ///
 /// 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 @@ fn as_into_iter(&mut self) -> &mut IntoIter<Self::Item> {
 ///
 /// 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 @@ unsafe fn move_tail(&mut self, additional: usize) {
 ///
 /// 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>
index cbde2a7e28e8f134004678ecd8b64478c27f4943..a7239a4b14fae82bf92be0ae533f98ccc148bd79 100644 (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] {
index c1fda2fce641fead20d505a0e293dfb4d10d9b01..f9eb8981bbfc24d1a8dafeb52803d4b391edec3c 100644 (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 @@ fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
     ///
     /// [*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 @@ fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
     ///
     /// [`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 @@ unsafe fn grow(
     ///
     /// [`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 @@ unsafe fn grow_zeroed(
     ///
     /// [`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 @@ unsafe fn shrink(
     ///
     /// 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 @@ unsafe fn grow(
 
     #[inline]
     unsafe fn grow_zeroed(
-        &mut self,
+        &self,
         ptr: NonNull<u8>,
         old_layout: Layout,
         new_layout: Layout,
@@ -387,7 +387,7 @@ unsafe fn grow_zeroed(
 
     #[inline]
     unsafe fn shrink(
-        &mut self,
+        &self,
         ptr: NonNull<u8>,
         old_layout: Layout,
         new_layout: Layout,
index f60aa2d24c5cafd0599f933cd758f63f9dddf0dc..15ec13ca65a18db729a174cc04bfaf770de69f4f 100644 (file)
@@ -697,6 +697,7 @@ pub fn into_inner(self) -> 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 @@ pub fn replace(&self, t: T) -> 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())
     }
index 7eec2c487fef42a935ff765e29e6d00bb5c39682..5c9cfe27101f07edbcfbbe669bf4074ec0385584 100644 (file)
@@ -327,6 +327,28 @@ pub fn get_mut(&mut self) -> &mut bool {
         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 @@ pub fn get_mut(&mut self) -> &mut *mut 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 @@ pub fn get_mut(&mut self) -> &mut $int_type {
                 }
             }
 
+            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 @@ pub fn as_mut_ptr(&self) -> *mut $int_type {
 #[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 @@ pub fn as_mut_ptr(&self) -> *mut $int_type {
 #[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 @@ pub fn as_mut_ptr(&self) -> *mut $int_type {
 #[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 @@ pub fn as_mut_ptr(&self) -> *mut $int_type {
 #[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 @@ pub fn as_mut_ptr(&self) -> *mut $int_type {
 #[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 @@ pub fn as_mut_ptr(&self) -> *mut $int_type {
 #[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 @@ pub fn as_mut_ptr(&self) -> *mut $int_type {
 #[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 @@ pub fn as_mut_ptr(&self) -> *mut $int_type {
 #[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 @@ pub fn as_mut_ptr(&self) -> *mut $int_type {
 #[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 @@ pub fn as_mut_ptr(&self) -> *mut $int_type {
 #[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 @@ 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"),
index 770c97899f00253b5f429547e0d19c35696dacd6..ba158511f64c085eae97538d255f77bebc398c95 100644 (file)
 
 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 @@ fn alloc_impl(&mut self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>,
     // 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 @@ unsafe fn grow_impl(
             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 @@ unsafe fn grow_impl(
 #[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 fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
 
     #[inline]
     unsafe fn grow(
-        &mut self,
+        &self,
         ptr: NonNull<u8>,
         old_layout: Layout,
         new_layout: Layout,
@@ -233,7 +233,7 @@ unsafe fn grow(
 
     #[inline]
     unsafe fn grow_zeroed(
-        &mut self,
+        &self,
         ptr: NonNull<u8>,
         old_layout: Layout,
         new_layout: Layout,
@@ -244,7 +244,7 @@ unsafe fn grow_zeroed(
 
     #[inline]
     unsafe fn shrink(
-        &mut self,
+        &self,
         ptr: NonNull<u8>,
         old_layout: Layout,
         new_layout: Layout,
@@ -257,7 +257,7 @@ unsafe fn shrink(
         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 fn shrink(
             // `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)
             },
         }
index 499b1137dcba5bcaa32cb700724e1e3fb4e813a6..e213963d25046b836e446200333cdbeef05345fd 100644 (file)
@@ -745,9 +745,9 @@ fn hash<H: hash::Hasher>(&self, s: &mut H) {
 ///    `(`[`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
index a6c2317c73669efeee0467bc1ad91cfcf1070e1d..dfb5d3e9e38d0fb40cd49abd79cf1d32df56d6ce 100644 (file)
@@ -10,6 +10,7 @@
 
 use std::alloc::{self, AllocRef, Global, Layout, System};
 use std::sync::atomic::{AtomicUsize, Ordering};
+use std::ptr::NonNull;
 
 static HITS: AtomicUsize = AtomicUsize::new(0);
 
 unsafe impl alloc::GlobalAlloc for A {
     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
         HITS.fetch_add(1, Ordering::SeqCst);
-        System.alloc(layout)
+        alloc::GlobalAlloc::alloc(&System, layout)
     }
 
     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
         HITS.fetch_add(1, Ordering::SeqCst);
-        System.dealloc(ptr, layout)
+        AllocRef::dealloc(&System, NonNull::new(ptr).unwrap(), layout)
     }
 }
 
diff --git a/src/test/ui/atomic-from-mut-not-available.rs b/src/test/ui/atomic-from-mut-not-available.rs
new file mode 100644 (file)
index 0000000..bf94616
--- /dev/null
@@ -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`
+}
diff --git a/src/test/ui/atomic-from-mut-not-available.stderr b/src/test/ui/atomic-from-mut-not-available.stderr
new file mode 100644 (file)
index 0000000..d1ebca8
--- /dev/null
@@ -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`.
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/closures.rs b/src/test/ui/const-generics/const_evaluatable_checked/closures.rs
new file mode 100644 (file)
index 0000000..32f4359
--- /dev/null
@@ -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() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/closures.stderr b/src/test/ui/const-generics/const_evaluatable_checked/closures.stderr
new file mode 100644 (file)
index 0000000..9f0b725
--- /dev/null
@@ -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
+
index d96788f8cd100510437c26612f9368f23313cfa6..a6bb39208a42d9d2b16a0c0ec4013d652ac18f20 100644 (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()
 }
 
index 95fb48bd434027c88245a0a1864b74f3f0233822..5749defb3e12c679227424fb7eef06d8bf66ad61 100644 (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
 
index 8236250392fd65b047265be181c58219d60336c3..eb1b42c57bc51f905566b45ec2e76c69e082e6c2 100644 (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
    |
index 506b21dc7d54488a5e853ac435174f25f6e3c75e..049fdd84d8c22e71a8dae4a329b97cfbe60f74fe 100644 (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]
index 6132c5308787914eae64c2ae645056722b32eeb5..16e1dc644008433ca55be33c2449b5fed9309028 100644 (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`.
index 65b67a94238760598f6d0592bce263f31e93c93d..63b8b29d6ce2861db2a879c6d2d2bca76fa67d3c 100644 (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)
index e522bd258e14b0d36cb1fe109103fac76e3c5a50..81cebae17aeba4d1690326f5831650a86638be59 100644 (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
index dddde482ef99b9c7ca5b0ba1d6bd1e10d0888804..662682d40b2c68640e5c057d43f531802f1e90c7 100644 (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 []
index 3efe13b3de3d0f9e93aa411111f9b7a8eef7e59e..5bf381607c5ed6eb78b7886bc211e17270f6d38f 100644 (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
index 1c0a596a64cb9fa04828a34b5a57fa7d22c62b20..a2ddffff997d882af39f5f3ac15b1c9c34b8566f 100644 (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