From d4039c55c9ef392261aeaba6c14ae81f5098139a Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 19 Sep 2020 22:17:52 +0200 Subject: [PATCH 01/28] wip emit errors during AbstractConst building --- compiler/rustc_metadata/src/rmeta/decoder.rs | 5 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 4 +- compiler/rustc_trait_selection/src/lib.rs | 1 + .../src/traits/const_evaluatable.rs | 193 +++++++++++------- 5 files changed, 125 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index a2e2cf1ca0219..72d54a26b01d4 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -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]>, 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 { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index eb091d86b82c6..3500ec7455429 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -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); } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 44d906dada5f0..86fb0664a5c62 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -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]>, 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]>, ErrorReported> { desc { |tcx| "building an abstract representation for the const argument {}", diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index da1996b92a60b..a53075448eddc 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -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 diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 2642358dbc54c..6c0c1df1b530f 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -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,9 @@ 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).map_err(ErrorHandled::Reported)? + { for pred in param_env.caller_bounds() { match pred.skip_binders() { ty::PredicateAtom::ConstEvaluatable(b_def, b_substs) => { @@ -40,6 +43,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( debug!("is_const_evaluatable: caller_bound ~~> ok"); return Ok(()); } else if AbstractConst::new(infcx.tcx, b_def, b_substs) + .map_err(ErrorHandled::Reported)? .map_or(false, |b_ct| try_unify(infcx.tcx, ct, b_ct)) { debug!("is_const_evaluatable: abstract_const ~~> ok"); @@ -114,7 +118,7 @@ impl AbstractConst<'tcx> { tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam, substs: SubstsRef<'tcx>, - ) -> Option> { + ) -> Result>, 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 +126,7 @@ impl AbstractConst<'tcx> { _ => tcx.mir_abstract_const(def.did)?, }; - Some(AbstractConst { inner, substs }) + Ok(inner.map(|inner| AbstractConst { inner, substs })) } #[inline] @@ -148,53 +152,85 @@ struct AbstractConstBuilder<'a, 'tcx> { } impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { - fn new(tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>) -> Option> { - // 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, msg: &str) -> Result { + let mut err = + self.tcx.sess.struct_span_err(self.body.span, "overly complex generic constant"); + if let Some(span) = span { + err.span_note(span, msg); + } else { + err.note(msg); } + err.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>, 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 { - debug!("operand_to_node: op={:?}", op); + + fn place_to_local( + &mut self, + span: Span, + p: &mir::Place<'tcx>, + ) -> Result { 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 { + 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 +253,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 +303,11 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { fn build_terminator( &mut self, terminator: &mir::Terminator<'tcx>, - ) -> Option> { + ) -> Result, 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 +325,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::>>()?, + .map(|arg| self.operand_to_node(terminator.source_info.span, arg)) + .collect::, _>>()?, ); 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 +352,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 +376,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 +386,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { pub(super) fn mir_abstract_const<'tcx>( tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam, -) -> Option<&'tcx [Node<'tcx>]> { +) -> Result]>, 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 +395,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 +411,19 @@ pub(super) fn try_unify_abstract_consts<'tcx>( (ty::WithOptConstParam, 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 `Error`. } /// Tries to unify two abstract constants using structural equality. From 30cbc9729654c66b9f54779d18f023e47112cdf2 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 19 Sep 2020 22:27:52 +0200 Subject: [PATCH 02/28] words --- compiler/rustc_trait_selection/src/traits/const_evaluatable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 6c0c1df1b530f..12082475c85d4 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -423,7 +423,7 @@ pub(super) fn try_unify_abstract_consts<'tcx>( .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 `Error`. + // on `ErrorReported`. } /// Tries to unify two abstract constants using structural equality. From 16047d46a10813a25e956e659b8861cc67c20cd2 Mon Sep 17 00:00:00 2001 From: yuk1ty Date: Mon, 21 Sep 2020 12:14:28 +0900 Subject: [PATCH 03/28] fix typo in docs and comments --- compiler/rustc_lint/src/types.rs | 2 +- compiler/rustc_middle/src/mir/predecessors.rs | 2 +- compiler/rustc_mir/src/borrow_check/member_constraints.rs | 2 +- compiler/rustc_mir_build/src/build/matches/mod.rs | 2 +- compiler/rustc_parse/src/parser/ty.rs | 2 +- compiler/rustc_span/src/symbol.rs | 2 +- compiler/rustc_target/src/spec/wasm32_wasi.rs | 2 +- compiler/rustc_typeck/src/check/mod.rs | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index ccbe9f80e25b7..6aa28d04ae197 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -733,7 +733,7 @@ fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option 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 diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 6e9d5eedf051f..a9b8a6181d499 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -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, diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index fc4c62ccbd90e..d42a786a18fe9 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -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> { self.parse_ty_common(AllowPlus::Yes, RecoverQPath::Yes, AllowCVariadic::Yes) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6085eedf23694..65a26284186bd 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -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 diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs index 0bba7bdd4735c..351167105ec7a 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi.rs +++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs @@ -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 diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index e84cc3c9b8684..b85ffb535ff9d 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -1843,7 +1843,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); From db74e1f1e3e5c7497bb9af68814497c8df1fd0b8 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 20 Sep 2020 12:09:22 +0200 Subject: [PATCH 04/28] Add cfg(target_has_atomic_equal_alignment). This is needed for Atomic::from_mut. --- compiler/rustc_feature/src/builtin_attrs.rs | 5 +++++ compiler/rustc_session/src/config.rs | 19 +++++++++++++++---- compiler/rustc_span/src/symbol.rs | 1 + 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index fc122db8ac1b1..8b7fd59cd874a 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -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)), ]; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 8d004675d7f4d..09e5948cdd750 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -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,7 @@ 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(); let mut ret = FxHashSet::default(); ret.reserve(6); // the minimum number of insertions @@ -769,18 +771,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); } } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6085eedf23694..60688d26d4ce0 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -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, From 9e3f94dabc334586d669f3aba0bded607ac782fc Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 20 Sep 2020 12:39:07 +0200 Subject: [PATCH 05/28] Don't unwrap but report a fatal error for TargetDataLayout::parse. --- compiler/rustc_session/src/config.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 09e5948cdd750..ab96b0333f43f 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -749,7 +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(); + 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 From af56ad7633668a790353f17440586e97b4e6a99b Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 20 Sep 2020 13:03:12 +0200 Subject: [PATCH 06/28] Add feature gate ui test for cfg(target_has_atomic_load_store). --- .../feature-gate-cfg-target-has-atomic.rs | 12 ++++ .../feature-gate-cfg-target-has-atomic.stderr | 56 ++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs index 506b21dc7d544..e336c63071814 100644 --- a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs +++ b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs @@ -87,6 +87,18 @@ 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 } #[macro_export] diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr index 6132c53087879..c171d8e6d92fc 100644 --- a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr +++ b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr @@ -160,6 +160,60 @@ LL | cfg!(target_has_atomic = "ptr"); = note: see issue #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 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 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 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 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 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 for more information + = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable + +error: aborting due to 24 previous errors For more information about this error, try `rustc --explain E0658`. From 54fdf54e06e3287958d906d2fb1b905b778d5e38 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 20 Sep 2020 13:03:12 +0200 Subject: [PATCH 07/28] Add feature gate ui test for cfg(target_has_atomic_equal_alignment). --- .../feature-gate-cfg-target-has-atomic.rs | 12 ++++ .../feature-gate-cfg-target-has-atomic.stderr | 56 ++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs index e336c63071814..049fdd84d8c22 100644 --- a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs +++ b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs @@ -99,6 +99,18 @@ fn main() { //~^ 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] diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr index c171d8e6d92fc..16e1dc6440084 100644 --- a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr +++ b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr @@ -214,6 +214,60 @@ LL | cfg!(target_has_atomic_load_store = "ptr"); = note: see issue #32976 for more information = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable -error: aborting due to 24 previous errors +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 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 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 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 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 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 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`. From 668225d157d91e5c55a02aa7abc1b65ec9690ffa Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 21 Sep 2020 20:42:40 +0200 Subject: [PATCH 08/28] Revert "Revert adding Atomic::from_mut." This reverts commit 5ef1db3622c373883571868cbdafbfbd568cddcb. --- library/core/src/sync/atomic.rs | 90 +++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 7eec2c487fef4..c67d6422c01ec 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -110,6 +110,7 @@ use self::Ordering::*; use crate::cell::UnsafeCell; use crate::fmt; use crate::intrinsics; +use crate::mem::align_of; use crate::hint::spin_loop; @@ -327,6 +328,27 @@ 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] + #[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,30 @@ impl AtomicPtr { 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] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn from_mut(v: &mut *mut T) -> &Self { + let [] = [(); align_of::>() - 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 @@ -1121,6 +1167,7 @@ macro_rules! atomic_int { $stable_nand:meta, $const_stable:meta, $stable_init_const:meta, + $(from_mut: cfg($from_mut_cfg:meta),)? $s_int_type:literal, $int_ref:expr, $extra_feature:expr, $min_fn:ident, $max_fn:ident, @@ -1231,6 +1278,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($from_mut_cfg)])? + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn from_mut(v: &mut $int_type) -> &Self { + let [] = [(); align_of::() - align_of::<$int_type>()]; + // SAFETY: + // - the mutable reference guarantees unique ownership. + // - the alignment of `$int_type` and `Self` is the + // same on all platforms enabled by `$from_mut_cfg` + // as verified above. + unsafe { &*(v as *mut $int_type as *mut Self) } + } + } + doc_comment! { concat!("Consumes the atomic and returns the contained value. @@ -1989,6 +2075,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), + from_mut: cfg(not(target_arch = "x86")), "i64", "../../../std/primitive.i64.html", "", atomic_min, atomic_max, @@ -2007,6 +2094,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), + from_mut: cfg(not(target_arch = "x86")), "u64", "../../../std/primitive.u64.html", "", atomic_umin, atomic_umax, @@ -2025,6 +2113,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), + from_mut: cfg(not(target_arch = "x86_64")), "i128", "../../../std/primitive.i128.html", "#![feature(integer_atomics)]\n\n", atomic_min, atomic_max, @@ -2043,6 +2132,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), + from_mut: cfg(not(target_arch = "x86_64")), "u128", "../../../std/primitive.u128.html", "#![feature(integer_atomics)]\n\n", atomic_umin, atomic_umax, From 7a04ff6c33c8bc9b8b1012e12a9920df52956e2f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 20 Sep 2020 12:14:41 +0200 Subject: [PATCH 09/28] Gate Atomic::from_mut on cfg(target_has_atomic_equal_alignment). Instead of a few hardcoded cfg(target_arch = ..) like before. --- library/core/src/sync/atomic.rs | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index c67d6422c01ec..fa9d3c95b1790 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -110,6 +110,8 @@ use self::Ordering::*; use crate::cell::UnsafeCell; use crate::fmt; use crate::intrinsics; + +#[allow(unused_imports)] use crate::mem::align_of; use crate::hint::spin_loop; @@ -342,6 +344,7 @@ impl AtomicBool { /// 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 @@ -855,6 +858,7 @@ impl AtomicPtr { /// 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 { let [] = [(); align_of::>() - align_of::<*mut ()>()]; @@ -1159,6 +1163,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, @@ -1167,7 +1172,6 @@ macro_rules! atomic_int { $stable_nand:meta, $const_stable:meta, $stable_init_const:meta, - $(from_mut: cfg($from_mut_cfg:meta),)? $s_int_type:literal, $int_ref:expr, $extra_feature:expr, $min_fn:ident, $max_fn:ident, @@ -1304,15 +1308,14 @@ assert_eq!(some_int, 100); ``` "), #[inline] - $(#[cfg($from_mut_cfg)])? + #[$cfg_align] #[unstable(feature = "atomic_from_mut", issue = "76314")] pub fn from_mut(v: &mut $int_type) -> &Self { let [] = [(); align_of::() - align_of::<$int_type>()]; // SAFETY: // - the mutable reference guarantees unique ownership. // - the alignment of `$int_type` and `Self` is the - // same on all platforms enabled by `$from_mut_cfg` - // as verified above. + // same, as promised by $cfg_align and verified above. unsafe { &*(v as *mut $int_type as *mut Self) } } } @@ -1959,6 +1962,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"), @@ -1977,6 +1981,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"), @@ -1995,6 +2000,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"), @@ -2013,6 +2019,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"), @@ -2031,6 +2038,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"), @@ -2049,6 +2057,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"), @@ -2067,6 +2076,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"), @@ -2075,7 +2085,6 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), - from_mut: cfg(not(target_arch = "x86")), "i64", "../../../std/primitive.i64.html", "", atomic_min, atomic_max, @@ -2086,6 +2095,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"), @@ -2094,7 +2104,6 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), - from_mut: cfg(not(target_arch = "x86")), "u64", "../../../std/primitive.u64.html", "", atomic_umin, atomic_umax, @@ -2105,6 +2114,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"), @@ -2113,7 +2123,6 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), - from_mut: cfg(not(target_arch = "x86_64")), "i128", "../../../std/primitive.i128.html", "#![feature(integer_atomics)]\n\n", atomic_min, atomic_max, @@ -2124,6 +2133,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"), @@ -2132,7 +2142,6 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), - from_mut: cfg(not(target_arch = "x86_64")), "u128", "../../../std/primitive.u128.html", "#![feature(integer_atomics)]\n\n", atomic_umin, atomic_umax, @@ -2164,6 +2173,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"), @@ -2182,6 +2192,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"), From 5d6f1a1e32de4936e5b269b04781b2737f6d410b Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 21 Sep 2020 20:44:45 +0200 Subject: [PATCH 10/28] Move `use align_of` in atomic.rs into the places where it is used. --- library/core/src/sync/atomic.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index fa9d3c95b1790..5c9cfe27101f0 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -111,9 +111,6 @@ use crate::cell::UnsafeCell; use crate::fmt; use crate::intrinsics; -#[allow(unused_imports)] -use crate::mem::align_of; - use crate::hint::spin_loop; /// Signals the processor that it is inside a busy-wait spin-loop ("spin lock"). @@ -861,6 +858,7 @@ impl AtomicPtr { #[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::>() - align_of::<*mut ()>()]; // SAFETY: // - the mutable reference guarantees unique ownership. @@ -1311,6 +1309,7 @@ assert_eq!(some_int, 100); #[$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::() - align_of::<$int_type>()]; // SAFETY: // - the mutable reference guarantees unique ownership. From e734733a9e931cbbe26cfccbdf9849faef8e5125 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 18 Sep 2020 21:49:11 -0400 Subject: [PATCH 11/28] Record `tcx.def_span` instead of `item.span` in crate metadata This was missed in PR #75465. As a result, a few places have been using the full body span of functions, instead of just the header span. --- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- src/test/ui/consts/miri_unleashed/drop.stderr | 20 +++++++------------ src/test/ui/macros/same-sequence-span.stderr | 12 ++++------- .../ui/proc-macro/meta-macro-hygiene.stdout | 4 ++-- src/test/ui/proc-macro/meta-macro.stdout | 2 +- ...-38591-non-regular-dropck-recursion.stderr | 20 ++++--------------- src/test/ui/type_length_limit.stderr | 2 +- 7 files changed, 20 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index eb091d86b82c6..d5b0a868a364e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -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 { diff --git a/src/test/ui/consts/miri_unleashed/drop.stderr b/src/test/ui/consts/miri_unleashed/drop.stderr index 8236250392fd6..eb1b42c57bc51 100644 --- a/src/test/ui/consts/miri_unleashed/drop.stderr +++ b/src/test/ui/consts/miri_unleashed/drop.stderr @@ -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(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 ` as Drop>::drop` - | inside `drop_in_place::> - shim(Some(Vec))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL +LL | pub unsafe fn drop_in_place(to_drop: *mut T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | calling non-const function ` as Drop>::drop` + | inside `drop_in_place::> - shim(Some(Vec))` 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 | diff --git a/src/test/ui/macros/same-sequence-span.stderr b/src/test/ui/macros/same-sequence-span.stderr index 65b67a9423876..63b8b29d6ce28 100644 --- a/src/test/ui/macros/same-sequence-span.stderr +++ b/src/test/ui/macros/same-sequence-span.stderr @@ -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) diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.stdout b/src/test/ui/proc-macro/meta-macro-hygiene.stdout index e522bd258e14b..81cebae17aeba 100644 --- a/src/test/ui/proc-macro/meta-macro-hygiene.stdout +++ b/src/test/ui/proc-macro/meta-macro-hygiene.stdout @@ -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 diff --git a/src/test/ui/proc-macro/meta-macro.stdout b/src/test/ui/proc-macro/meta-macro.stdout index dddde482ef99b..662682d40b2c6 100644 --- a/src/test/ui/proc-macro/meta-macro.stdout +++ b/src/test/ui/proc-macro/meta-macro.stdout @@ -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 [] diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr index 3efe13b3de3d0..5bf381607c5ed 100644 --- a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr +++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr @@ -1,26 +1,14 @@ error: reached the recursion limit while instantiating `drop_in_place::))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | -LL | / pub unsafe fn drop_in_place(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(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(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(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 diff --git a/src/test/ui/type_length_limit.stderr b/src/test/ui/type_length_limit.stderr index 1c0a596a64cb9..a2ddffff997d8 100644 --- a/src/test/ui/type_length_limit.stderr +++ b/src/test/ui/type_length_limit.stderr @@ -2,7 +2,7 @@ error: reached the type-length limit while instantiating `std::mem::drop:: $SRC_DIR/core/src/mem/mod.rs:LL:COL | LL | pub fn drop(_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 From bcc1d56917fe061071ebc539b5d2e304a44a7b00 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 21 Sep 2020 21:12:20 +0200 Subject: [PATCH 12/28] Test that AtomicU64::from_mut is not available on x86 linux. --- src/test/ui/atomic-from-mut-not-available.rs | 7 +++++++ src/test/ui/atomic-from-mut-not-available.stderr | 9 +++++++++ 2 files changed, 16 insertions(+) create mode 100644 src/test/ui/atomic-from-mut-not-available.rs create mode 100644 src/test/ui/atomic-from-mut-not-available.stderr 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 index 0000000000000..bf94616007570 --- /dev/null +++ b/src/test/ui/atomic-from-mut-not-available.rs @@ -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 index 0000000000000..d1ebca8a29e93 --- /dev/null +++ b/src/test/ui/atomic-from-mut-not-available.stderr @@ -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`. From 7a02ebd828c8d9c68e8e972326ede8696fb3f6b7 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 21 Sep 2020 21:50:00 +0200 Subject: [PATCH 13/28] bless tests --- .../const_evaluatable_checked/let-bindings.rs | 4 +-- .../let-bindings.stderr | 26 +++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.rs b/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.rs index d96788f8cd100..a6bb39208a42d 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.rs +++ b/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.rs @@ -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() -> [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() } diff --git a/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr b/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr index 95fb48bd43402..95fcde52af820 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr @@ -1,18 +1,28 @@ -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() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { - | ^^^^^^^ required by this bound in `test::{{constant}}#0` + | ^^^^^^^^^^^^^^^^^^^^ | - = note: this may fail depending on what value the parameter takes +note: unsupported statement + --> $DIR/let-bindings.rs:6:74 + | +LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { + | ^ + = 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() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | - = note: this may fail depending on what value the parameter takes +note: unsupported statement + --> $DIR/let-bindings.rs:6:41 + | +LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { + | ^ + = help: consider moving this anonymous constant into a `const` function error: aborting due to 2 previous errors From 9a493ced748e2e3e7390fc6f28640d23cb90e67b Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 21 Sep 2020 22:01:18 +0200 Subject: [PATCH 14/28] add test for closures in abstract consts --- .../const_evaluatable_checked/closures.rs | 6 ++++++ .../const_evaluatable_checked/closures.stderr | 15 +++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/closures.rs create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/closures.stderr 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 index 0000000000000..32f43591e37b9 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/closures.rs @@ -0,0 +1,6 @@ +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] +fn test() -> [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 index 0000000000000..7bb23f1488d93 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/closures.stderr @@ -0,0 +1,15 @@ +error: overly complex generic constant + --> $DIR/closures.rs:3:35 + | +LL | fn test() -> [u8; N + (|| 42)()] {} + | ^^^^^^^^^^^^^ + | +note: unsupported rvalue + --> $DIR/closures.rs:3:39 + | +LL | fn test() -> [u8; N + (|| 42)()] {} + | ^^^^^^^ + = help: consider moving this anonymous constant into a `const` function + +error: aborting due to previous error + From 2f893e458a20a159fcf93a9a5b0435ae3ed0a67e Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 21 Sep 2020 23:25:52 +0200 Subject: [PATCH 15/28] review --- .../rustc_middle/src/mir/interpret/error.rs | 6 ++++++ .../src/traits/const_evaluatable.rs | 21 +++++++------------ .../const_evaluatable_checked/closures.stderr | 9 +++----- .../let-bindings.stderr | 18 ++++++---------- 4 files changed, 23 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 059925088ce1d..97a13ee8e20e9 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -23,6 +23,12 @@ pub enum ErrorHandled { TooGeneric, } +impl From for ErrorHandled { + fn from(err: ErrorReported) -> ErrorHandled { + ErrorHandled::Reported(err) + } +} + CloneTypeFoldableAndLiftImpls! { ErrorHandled, } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 12082475c85d4..0cfcaca906033 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -32,9 +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).map_err(ErrorHandled::Reported)? - { + 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) => { @@ -42,8 +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) - .map_err(ErrorHandled::Reported)? + } 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"); @@ -153,14 +150,12 @@ struct AbstractConstBuilder<'a, 'tcx> { impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { fn error(&mut self, span: Option, msg: &str) -> Result { - let mut err = - self.tcx.sess.struct_span_err(self.body.span, "overly complex generic constant"); - if let Some(span) = span { - err.span_note(span, msg); - } else { - err.note(msg); - } - err.help("consider moving this anonymous constant into a `const` function").emit(); + 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(); Err(ErrorReported) } diff --git a/src/test/ui/const-generics/const_evaluatable_checked/closures.stderr b/src/test/ui/const-generics/const_evaluatable_checked/closures.stderr index 7bb23f1488d93..9f0b7252e8326 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/closures.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/closures.stderr @@ -2,13 +2,10 @@ error: overly complex generic constant --> $DIR/closures.rs:3:35 | LL | fn test() -> [u8; N + (|| 42)()] {} - | ^^^^^^^^^^^^^ + | ^^^^-------^^ + | | + | unsupported rvalue | -note: unsupported rvalue - --> $DIR/closures.rs:3:39 - | -LL | fn test() -> [u8; N + (|| 42)()] {} - | ^^^^^^^ = help: consider moving this anonymous constant into a `const` function error: aborting due to previous error diff --git a/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr b/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr index 95fcde52af820..5749defb3e12c 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr @@ -2,26 +2,20 @@ error: overly complex generic constant --> $DIR/let-bindings.rs:6:68 | LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^-^^^^^^^^^^^^^ + | | + | unsupported statement | -note: unsupported statement - --> $DIR/let-bindings.rs:6:74 - | -LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { - | ^ = help: consider moving this anonymous constant into a `const` function error: overly complex generic constant --> $DIR/let-bindings.rs:6:35 | LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^-^^^^^^^^^^^^^ + | | + | unsupported statement | -note: unsupported statement - --> $DIR/let-bindings.rs:6:41 - | -LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { - | ^ = help: consider moving this anonymous constant into a `const` function error: aborting due to 2 previous errors From d9d02fa168016b5b5b2033a2964a723f447f94b0 Mon Sep 17 00:00:00 2001 From: blitzerr Date: Sun, 20 Sep 2020 20:14:44 -0700 Subject: [PATCH 16/28] Changing the alloc() to accept &self instead of &mut self --- library/alloc/src/alloc.rs | 4 ++-- library/alloc/src/raw_vec/tests.rs | 15 ++++++++------- library/core/src/alloc/mod.rs | 4 ++-- library/std/src/alloc.rs | 4 ++-- src/test/ui/allocator/custom.rs | 2 +- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 341c6816197c7..7d872b1a66bb9 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -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, AllocErr> { + fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result, AllocErr> { match layout.size() { 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), // SAFETY: `layout` is non-zero in size, @@ -208,7 +208,7 @@ impl Global { #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl AllocRef for Global { #[inline] - fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { + fn alloc(&self, layout: Layout) -> Result, AllocErr> { self.alloc_impl(layout, false) } diff --git a/library/alloc/src/raw_vec/tests.rs b/library/alloc/src/raw_vec/tests.rs index cadd913aa6bf2..f348710d61a77 100644 --- a/library/alloc/src/raw_vec/tests.rs +++ b/library/alloc/src/raw_vec/tests.rs @@ -1,4 +1,5 @@ use super::*; +use std::cell::Cell; #[test] fn allocator_param() { @@ -17,17 +18,17 @@ fn allocator_param() { // A dumb allocator that consumes a fixed amount of fuel // before allocation attempts start failing. struct BoundedAlloc { - fuel: usize, + fuel: Cell, } unsafe impl AllocRef for BoundedAlloc { - fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { + fn alloc(&self, layout: Layout) -> Result, 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.update(|old| old - size); ok } err @ Err(_) => err, @@ -38,11 +39,11 @@ fn allocator_param() { } } - let a = BoundedAlloc { fuel: 500 }; + let a = BoundedAlloc { fuel: Cell::new(500) }; let mut v: RawVec = 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] diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index c1fda2fce641f..b7dd249d09361 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -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, AllocErr>; + fn alloc(&self, layout: Layout) -> Result, AllocErr>; /// Behaves like `alloc`, but also ensures that the returned memory is zero-initialized. /// @@ -348,7 +348,7 @@ where A: AllocRef + ?Sized, { #[inline] - fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { + fn alloc(&self, layout: Layout) -> Result, AllocErr> { (**self).alloc(layout) } diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 770c97899f002..86ae4cf4dd213 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -133,7 +133,7 @@ pub struct System; impl System { #[inline] - fn alloc_impl(&mut self, layout: Layout, zeroed: bool) -> Result, AllocErr> { + fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result, AllocErr> { match layout.size() { 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), // SAFETY: `layout` is non-zero in size, @@ -202,7 +202,7 @@ impl System { #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl AllocRef for System { #[inline] - fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { + fn alloc(&self, layout: Layout) -> Result, AllocErr> { self.alloc_impl(layout, false) } diff --git a/src/test/ui/allocator/custom.rs b/src/test/ui/allocator/custom.rs index a6c2317c73669..603f59ab06927 100644 --- a/src/test/ui/allocator/custom.rs +++ b/src/test/ui/allocator/custom.rs @@ -18,7 +18,7 @@ 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) + AllocRef::alloc(&System, layout).unwrap().as_mut_ptr() } unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { From 7e443a1ffc587858c16aeac1dda3d2dffce0ff5f Mon Sep 17 00:00:00 2001 From: blitzerr Date: Mon, 21 Sep 2020 15:52:35 -0700 Subject: [PATCH 17/28] Added feature flag to use cell_update --- library/alloc/src/raw_vec/tests.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/alloc/src/raw_vec/tests.rs b/library/alloc/src/raw_vec/tests.rs index f348710d61a77..41d6c98b48196 100644 --- a/library/alloc/src/raw_vec/tests.rs +++ b/library/alloc/src/raw_vec/tests.rs @@ -1,6 +1,10 @@ +#![feature(cell_update)] + use super::*; use std::cell::Cell; + + #[test] fn allocator_param() { use crate::alloc::AllocErr; From 219003bd2ee6778333cf92405c6ea8591ecc8816 Mon Sep 17 00:00:00 2001 From: blitzerr Date: Mon, 21 Sep 2020 16:55:07 -0700 Subject: [PATCH 18/28] replaced cell::update with cell::[g|s]et --- library/alloc/src/raw_vec/tests.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/library/alloc/src/raw_vec/tests.rs b/library/alloc/src/raw_vec/tests.rs index 41d6c98b48196..2ed9d3685c69f 100644 --- a/library/alloc/src/raw_vec/tests.rs +++ b/library/alloc/src/raw_vec/tests.rs @@ -1,10 +1,6 @@ -#![feature(cell_update)] - use super::*; use std::cell::Cell; - - #[test] fn allocator_param() { use crate::alloc::AllocErr; @@ -32,7 +28,7 @@ fn allocator_param() { } match Global.alloc(layout) { ok @ Ok(_) => { - self.fuel.update(|old| old - size); + self.fuel.set(self.fuel.get() - size); ok } err @ Err(_) => err, From 2a40b6366245ddb38f4562da0b4f665f4d0e45d9 Mon Sep 17 00:00:00 2001 From: Imbolc Date: Tue, 22 Sep 2020 09:15:53 +0300 Subject: [PATCH 19/28] Update addr.rs I little clarification --- library/std/src/net/addr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/net/addr.rs b/library/std/src/net/addr.rs index 499b1137dcba5..a52e23de76ff4 100644 --- a/library/std/src/net/addr.rs +++ b/library/std/src/net/addr.rs @@ -747,7 +747,7 @@ impl hash::Hash for SocketAddrV6 { /// /// * `(`[`&str`]`, `[`u16`]`)`: the string should be either a string representation /// of an [`IpAddr`] address as expected by [`FromStr`] implementation or a host -/// name. +/// name. The second [`u16`] value of the tuple represents a port. /// /// * [`&str`]: the string should be either a string representation of a /// [`SocketAddr`] as expected by its [`FromStr`] implementation or a string like From 731113b8eeef206ff27b77cb9f0dc49e2762a1b4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Sep 2020 09:04:30 +0200 Subject: [PATCH 20/28] Miri: more informative deallocation error messages --- compiler/rustc_mir/src/interpret/memory.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_mir/src/interpret/memory.rs index 86e242c67d520..f3e373813ca53 100644 --- a/compiler/rustc_mir/src/interpret/memory.rs +++ b/compiler/rustc_mir/src/interpret/memory.rs @@ -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(), From 143557ec56124c246d6cf4c37398e657f84536e1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 21 Sep 2020 17:32:53 +0200 Subject: [PATCH 21/28] Add missing examples on Vec iter types --- library/alloc/src/vec.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index 9dbea0dc9e68b..b1f3b11ab9fd2 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -2797,6 +2797,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 { buf: NonNull, @@ -3040,6 +3047,13 @@ impl AsIntoIter for IntoIter { /// /// 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 @@ -3169,6 +3183,14 @@ impl 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> { @@ -3285,6 +3307,15 @@ impl 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> From 3ffd403c6b97f181c189a8eb5fbd30e3e7a95b43 Mon Sep 17 00:00:00 2001 From: blitzerr Date: Tue, 22 Sep 2020 06:22:02 -0700 Subject: [PATCH 22/28] removing &mut self for other methods of AllocRef --- library/alloc/src/alloc.rs | 4 ++-- library/alloc/src/raw_vec.rs | 2 +- library/alloc/src/raw_vec/tests.rs | 2 +- library/alloc/tests/heap.rs | 2 +- library/core/src/alloc/mod.rs | 8 ++++---- library/std/src/alloc.rs | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 7d872b1a66bb9..462bcd15fa941 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -213,12 +213,12 @@ unsafe impl AllocRef for Global { } #[inline] - fn alloc_zeroed(&mut self, layout: Layout) -> Result, AllocErr> { + fn alloc_zeroed(&self, layout: Layout) -> Result, AllocErr> { self.alloc_impl(layout, true) } #[inline] - unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { + unsafe fn dealloc(&self, ptr: NonNull, layout: Layout) { if layout.size() != 0 { // SAFETY: `layout` is non-zero in size, // other conditions must be upheld by the caller diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 62675665f037f..5b4a4957f6cb1 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -169,7 +169,7 @@ impl RawVec { 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::() == 0 { Self::new_in(alloc) } else { diff --git a/library/alloc/src/raw_vec/tests.rs b/library/alloc/src/raw_vec/tests.rs index 2ed9d3685c69f..e4c8b3709dfee 100644 --- a/library/alloc/src/raw_vec/tests.rs +++ b/library/alloc/src/raw_vec/tests.rs @@ -34,7 +34,7 @@ fn allocator_param() { err @ Err(_) => err, } } - unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { + unsafe fn dealloc(&self, ptr: NonNull, layout: Layout) { unsafe { Global.dealloc(ptr, layout) } } } diff --git a/library/alloc/tests/heap.rs b/library/alloc/tests/heap.rs index cbde2a7e28e8f..a7239a4b14fae 100644 --- a/library/alloc/tests/heap.rs +++ b/library/alloc/tests/heap.rs @@ -11,7 +11,7 @@ fn std_heap_overaligned_request() { check_overalign_requests(Global) } -fn check_overalign_requests(mut allocator: T) { +fn check_overalign_requests(allocator: T) { for &align in &[4, 8, 16, 32] { // less than and bigger than `MIN_ALIGN` for &size in &[align / 2, align - 1] { diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index b7dd249d09361..5f9092fe7037e 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -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, AllocErr> { + fn alloc_zeroed(&self, layout: Layout) -> Result, 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, layout: Layout); + unsafe fn dealloc(&self, ptr: NonNull, layout: Layout); /// Attempts to extend the memory block. /// @@ -353,12 +353,12 @@ where } #[inline] - fn alloc_zeroed(&mut self, layout: Layout) -> Result, AllocErr> { + fn alloc_zeroed(&self, layout: Layout) -> Result, AllocErr> { (**self).alloc_zeroed(layout) } #[inline] - unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { + unsafe fn dealloc(&self, ptr: NonNull, layout: Layout) { // SAFETY: the safety contract must be upheld by the caller unsafe { (**self).dealloc(ptr, layout) } } diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 86ae4cf4dd213..f41aa28b5ecb5 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -207,12 +207,12 @@ unsafe impl AllocRef for System { } #[inline] - fn alloc_zeroed(&mut self, layout: Layout) -> Result, AllocErr> { + fn alloc_zeroed(&self, layout: Layout) -> Result, AllocErr> { self.alloc_impl(layout, true) } #[inline] - unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { + unsafe fn dealloc(&self, ptr: NonNull, layout: Layout) { if layout.size() != 0 { // SAFETY: `layout` is non-zero in size, // other conditions must be upheld by the caller From 05c3a2b07dc66fabc874181ce1eebea192cb4b56 Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 22 Sep 2020 15:30:09 +0200 Subject: [PATCH 23/28] Add #[track_caller] to more panicking Cell functions Continuation of #74526 Adds the #[track_caller] attribute to almost all panicking Cell functions. The ones that borrow two Cells in their function body are spared, because the panic location helps pinpoint which of the two borrows failed. You'd need to have full debuginfo and backtraces enabled together with column info in order to be able to discern the cases. Column info is only available on non-Windows platforms. --- library/core/src/cell.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index cbbfcb4611321..8d37cffeef556 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -700,6 +700,7 @@ impl RefCell { /// ``` #[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) } @@ -722,6 +723,7 @@ impl RefCell { /// ``` #[inline] #[stable(feature = "refcell_replace_swap", since = "1.35.0")] + #[track_caller] pub fn replace_with T>(&self, f: F) -> T { let mut_borrow = &mut *self.borrow_mut(); let replacement = f(mut_borrow); @@ -1056,6 +1058,7 @@ impl Clone for RefCell { /// /// Panics if the value is currently mutably borrowed. #[inline] + #[track_caller] fn clone(&self) -> RefCell { RefCell::new(self.borrow().clone()) } From 14736ca20b2e5f60981743c6ee2dfa62db818767 Mon Sep 17 00:00:00 2001 From: blitzerr Date: Tue, 22 Sep 2020 08:51:20 -0700 Subject: [PATCH 24/28] fixing the custom.rs --- src/test/ui/allocator/custom.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/allocator/custom.rs b/src/test/ui/allocator/custom.rs index 603f59ab06927..f54ef1f0bc152 100644 --- a/src/test/ui/allocator/custom.rs +++ b/src/test/ui/allocator/custom.rs @@ -23,7 +23,7 @@ unsafe impl alloc::GlobalAlloc for A { unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { HITS.fetch_add(1, Ordering::SeqCst); - System.dealloc(ptr, layout) + AllocRef::dealloc(&System, ptr, layout) } } From 5ab714fdfe00db1dbac1adf2f56a850768d478b4 Mon Sep 17 00:00:00 2001 From: Imbolc Date: Tue, 22 Sep 2020 19:09:27 +0300 Subject: [PATCH 25/28] Update library/std/src/net/addr.rs Co-authored-by: Ivan Tham --- library/std/src/net/addr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/net/addr.rs b/library/std/src/net/addr.rs index a52e23de76ff4..16320ac3fe792 100644 --- a/library/std/src/net/addr.rs +++ b/library/std/src/net/addr.rs @@ -747,7 +747,7 @@ impl hash::Hash for SocketAddrV6 { /// /// * `(`[`&str`]`, `[`u16`]`)`: the string should be either a string representation /// of an [`IpAddr`] address as expected by [`FromStr`] implementation or a host -/// name. The second [`u16`] value of the tuple represents a port. +/// 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 From 4622ceb5e02a717afd2380bc416b0a19897731ee Mon Sep 17 00:00:00 2001 From: Imbolc Date: Tue, 22 Sep 2020 19:09:35 +0300 Subject: [PATCH 26/28] Update library/std/src/net/addr.rs Co-authored-by: Ivan Tham --- library/std/src/net/addr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/net/addr.rs b/library/std/src/net/addr.rs index 16320ac3fe792..e213963d25046 100644 --- a/library/std/src/net/addr.rs +++ b/library/std/src/net/addr.rs @@ -745,7 +745,7 @@ 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. [`u16`] is the port number. /// From 985dff9e7ed1fd7896b071eaf637fd531a690e91 Mon Sep 17 00:00:00 2001 From: blitzerr Date: Tue, 22 Sep 2020 20:16:13 -0700 Subject: [PATCH 27/28] fixing the test failure --- src/test/ui/allocator/custom.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/ui/allocator/custom.rs b/src/test/ui/allocator/custom.rs index f54ef1f0bc152..73750bf139a7d 100644 --- a/src/test/ui/allocator/custom.rs +++ b/src/test/ui/allocator/custom.rs @@ -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); @@ -23,7 +24,7 @@ unsafe impl alloc::GlobalAlloc for A { unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { HITS.fetch_add(1, Ordering::SeqCst); - AllocRef::dealloc(&System, ptr, layout) + AllocRef::dealloc(&System, NonNull::new(ptr).unwrap(), layout) } } From 2b19b14cecbcdd173e29a801baff71e31cae7331 Mon Sep 17 00:00:00 2001 From: blitzerr Date: Tue, 22 Sep 2020 21:04:31 -0700 Subject: [PATCH 28/28] a few more &mut self -> self changes --- library/alloc/src/alloc.rs | 8 ++++---- library/core/src/alloc/mod.rs | 16 ++++++++-------- library/std/src/alloc.rs | 16 ++++++++-------- src/test/ui/allocator/custom.rs | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 462bcd15fa941..8b8cdbf252555 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -160,7 +160,7 @@ impl Global { // SAFETY: Same as `AllocRef::grow` #[inline] unsafe fn grow_impl( - &mut self, + &self, ptr: NonNull, old_layout: Layout, new_layout: Layout, @@ -228,7 +228,7 @@ unsafe impl AllocRef for Global { #[inline] unsafe fn grow( - &mut self, + &self, ptr: NonNull, 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, old_layout: Layout, new_layout: Layout, @@ -250,7 +250,7 @@ unsafe impl AllocRef for Global { #[inline] unsafe fn shrink( - &mut self, + &self, ptr: NonNull, old_layout: Layout, new_layout: Layout, diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 5f9092fe7037e..f9eb8981bbfc2 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -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, 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, 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, old_layout: Layout, new_layout: Layout, @@ -337,13 +337,13 @@ 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 AllocRef for &mut A +unsafe impl AllocRef for &A where A: AllocRef + ?Sized, { @@ -365,7 +365,7 @@ where #[inline] unsafe fn grow( - &mut self, + &self, ptr: NonNull, old_layout: Layout, new_layout: Layout, @@ -376,7 +376,7 @@ where #[inline] unsafe fn grow_zeroed( - &mut self, + &self, ptr: NonNull, old_layout: Layout, new_layout: Layout, @@ -387,7 +387,7 @@ where #[inline] unsafe fn shrink( - &mut self, + &self, ptr: NonNull, old_layout: Layout, new_layout: Layout, diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index f41aa28b5ecb5..ba158511f64c0 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -152,7 +152,7 @@ impl System { // SAFETY: Same as `AllocRef::grow` #[inline] unsafe fn grow_impl( - &mut self, + &self, ptr: NonNull, 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) }, } @@ -222,7 +222,7 @@ unsafe impl AllocRef for System { #[inline] unsafe fn grow( - &mut self, + &self, ptr: NonNull, 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, old_layout: Layout, new_layout: Layout, @@ -244,7 +244,7 @@ unsafe impl AllocRef for System { #[inline] unsafe fn shrink( - &mut self, + &self, ptr: NonNull, 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) }, } diff --git a/src/test/ui/allocator/custom.rs b/src/test/ui/allocator/custom.rs index 73750bf139a7d..dfb5d3e9e38d0 100644 --- a/src/test/ui/allocator/custom.rs +++ b/src/test/ui/allocator/custom.rs @@ -19,7 +19,7 @@ struct A; unsafe impl alloc::GlobalAlloc for A { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { HITS.fetch_add(1, Ordering::SeqCst); - AllocRef::alloc(&System, layout).unwrap().as_mut_ptr() + alloc::GlobalAlloc::alloc(&System, layout) } unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {