From 0ff8f0b5782e736f75be6f36765791164d9f0db7 Mon Sep 17 00:00:00 2001 From: Alex <58638691+Alex-Velez@users.noreply.github.com> Date: Sun, 14 Aug 2022 21:06:01 -0500 Subject: [PATCH 01/22] Update src/test/assembly/x86_64-floating-point-clamp.rs Simple Clamp Function I thought this was more robust and easier to read. I also allowed this function to return early in order to skip the extra bound check (I'm sure the difference is negligible). I'm not sure if there was a reason for binding `self` to `x`; if so, please correct me. Simple Clamp Function for f64 I thought this was more robust and easier to read. I also allowed this function to return early in order to skip the extra bound check (I'm sure the difference is negligible). I'm not sure if there was a reason for binding `self` to `x`; if so, please correct me. Floating point clamp test f32 clamp using mut self f64 clamp using mut self Update library/core/src/num/f32.rs Update f64.rs Update x86_64-floating-point-clamp.rs Update src/test/assembly/x86_64-floating-point-clamp.rs Update x86_64-floating-point-clamp.rs Co-Authored-By: scottmcm --- library/core/src/num/f32.rs | 13 +++++----- library/core/src/num/f64.rs | 13 +++++----- .../assembly/x86_64-floating-point-clamp.rs | 25 +++++++++++++++++++ 3 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 src/test/assembly/x86_64-floating-point-clamp.rs diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 6548ad2e514fb..f485e45912136 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -1282,15 +1282,14 @@ impl f32 { #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "clamp", since = "1.50.0")] #[inline] - pub fn clamp(self, min: f32, max: f32) -> f32 { + pub fn clamp(mut self, min: f32, max: f32) -> f32 { assert!(min <= max); - let mut x = self; - if x < min { - x = min; + if self < min { + self = min; } - if x > max { - x = max; + if self > max { + self = max; } - x + self } } diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 75c92c2f8834a..3d385e3888a8b 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1280,15 +1280,14 @@ impl f64 { #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "clamp", since = "1.50.0")] #[inline] - pub fn clamp(self, min: f64, max: f64) -> f64 { + pub fn clamp(mut self, min: f64, max: f64) -> f64 { assert!(min <= max); - let mut x = self; - if x < min { - x = min; + if self < min { + self = min; } - if x > max { - x = max; + if self > max { + self = max; } - x + self } } diff --git a/src/test/assembly/x86_64-floating-point-clamp.rs b/src/test/assembly/x86_64-floating-point-clamp.rs new file mode 100644 index 0000000000000..3388b0e1abd73 --- /dev/null +++ b/src/test/assembly/x86_64-floating-point-clamp.rs @@ -0,0 +1,25 @@ +// Floating-point clamp is designed to be implementable as max+min, +// so check to make sure that's what it's actually emitting. + +// assembly-output: emit-asm +// compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel +// only-x86_64 + +// CHECK-LABEL: clamp_demo: +#[no_mangle] +pub fn clamp_demo(a: f32, x: f32, y: f32) -> f32 { + // CHECK: maxss + // CHECK: minss + a.clamp(x, y) +} + +// CHECK-LABEL: clamp12_demo: +#[no_mangle] +pub fn clamp12_demo(a: f32) -> f32 { + // CHECK-NEXT: movss xmm1 + // CHECK-NEXT: maxss xmm1, xmm0 + // CHECK-NEXT: movss xmm0 + // CHECK-NEXT: minss xmm0, xmm1 + // CHECK-NEXT: ret + a.clamp(1.0, 2.0) +} From 302689fa7bbfc9b24b0bc73db41f7fce5586987c Mon Sep 17 00:00:00 2001 From: Alex <58638691+Alex-Velez@users.noreply.github.com> Date: Tue, 16 Aug 2022 20:39:22 -0500 Subject: [PATCH 02/22] Update src/test/assembly/x86_64-floating-point-clamp.rs Co-authored-by: scottmcm --- src/test/assembly/x86_64-floating-point-clamp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/assembly/x86_64-floating-point-clamp.rs b/src/test/assembly/x86_64-floating-point-clamp.rs index 3388b0e1abd73..4493791a5769f 100644 --- a/src/test/assembly/x86_64-floating-point-clamp.rs +++ b/src/test/assembly/x86_64-floating-point-clamp.rs @@ -16,7 +16,7 @@ pub fn clamp_demo(a: f32, x: f32, y: f32) -> f32 { // CHECK-LABEL: clamp12_demo: #[no_mangle] pub fn clamp12_demo(a: f32) -> f32 { - // CHECK-NEXT: movss xmm1 + // CHECK: movss xmm1 // CHECK-NEXT: maxss xmm1, xmm0 // CHECK-NEXT: movss xmm0 // CHECK-NEXT: minss xmm0, xmm1 From 5e1730fd17145fd9db5c042b127e2f400c83738a Mon Sep 17 00:00:00 2001 From: ltdk Date: Wed, 17 Aug 2022 02:01:32 -0400 Subject: [PATCH 03/22] Make slice::reverse const --- library/core/src/slice/mod.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index e79d47c9f98cd..361862cdd5257 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -674,8 +674,9 @@ impl [T] { /// assert!(v == [3, 2, 1]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_reverse", issue = "none")] #[inline] - pub fn reverse(&mut self) { + pub const fn reverse(&mut self) { let half_len = self.len() / 2; let Range { start, end } = self.as_mut_ptr_range(); @@ -698,9 +699,9 @@ impl [T] { revswap(front_half, back_half, half_len); #[inline] - fn revswap(a: &mut [T], b: &mut [T], n: usize) { - debug_assert_eq!(a.len(), n); - debug_assert_eq!(b.len(), n); + const fn revswap(a: &mut [T], b: &mut [T], n: usize) { + debug_assert!(a.len() == n); + debug_assert!(b.len() == n); // Because this function is first compiled in isolation, // this check tells LLVM that the indexing below is @@ -708,8 +709,10 @@ impl [T] { // lengths of the slices are known -- it's removed. let (a, b) = (&mut a[..n], &mut b[..n]); - for i in 0..n { + let mut i = 0; + while i < n { mem::swap(&mut a[i], &mut b[n - 1 - i]); + i += 1; } } } From 934d259b8ca1237c3fb50be21b8bba5ec8e6a7ce Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 19 Aug 2022 14:35:15 +0200 Subject: [PATCH 04/22] Fix invalid comparison for Class::Decoration in `is_equal_to` --- src/librustdoc/html/highlight.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 9d8ee52a3faf8..944cf08851240 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -291,8 +291,8 @@ impl Class { match (self, other) { (Self::Self_(_), Self::Self_(_)) | (Self::Macro(_), Self::Macro(_)) - | (Self::Ident(_), Self::Ident(_)) - | (Self::Decoration(_), Self::Decoration(_)) => true, + | (Self::Ident(_), Self::Ident(_)) => true, + (Self::Decoration(c1), Self::Decoration(c2)) => c1 == c2, (x, y) => x == y, } } From 7d2083c58ea9208c456b0bef177d87665e8c8a4f Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 7 Apr 2022 11:16:37 +0200 Subject: [PATCH 05/22] small mir typeck cleanup --- compiler/rustc_borrowck/src/type_check/canonical.rs | 7 ++++--- .../rustc_borrowck/src/type_check/free_region_relations.rs | 2 +- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 6cfe5efb68886..451b82c5c1870 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -90,12 +90,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations: Locations, category: ConstraintCategory<'tcx>, ) { - self.prove_predicates( - Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate { + self.prove_predicate( + ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: ty::BoundConstness::NotConst, polarity: ty::ImplPolarity::Positive, - }))), + })) + .to_predicate(self.tcx()), locations, category, ); diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 74655369faf03..bb28622edf931 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -268,7 +268,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { // } // impl Foo for () { // type Bar = (); - // fn foo(&self) ->&() {} + // fn foo(&self) -> &() {} // } // ``` // Both &Self::Bar and &() are WF diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 7bf7f7357bf4f..bb2e773189c03 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1911,7 +1911,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - &Rvalue::NullaryOp(_, ty) => { + &Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => { let trait_ref = ty::TraitRef { def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)), substs: tcx.mk_substs_trait(ty, &[]), From 56b5ec83f2ade19fc601ad44a7366d3e5215401a Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 7 Apr 2022 11:28:31 +0200 Subject: [PATCH 06/22] move `type_check_internal` into `type_check` --- compiler/rustc_borrowck/src/type_check/mod.rs | 137 +++++++----------- 1 file changed, 52 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index bb2e773189c03..293d847ec9ab7 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -178,97 +178,15 @@ pub(crate) fn type_check<'mir, 'tcx>( upvars, }; - let opaque_type_values = type_check_internal( + let mut checker = TypeChecker::new( infcx, - param_env, body, - promoted, + param_env, ®ion_bound_pairs, implicit_region_bound, &mut borrowck_context, - |mut cx| { - debug!("inside extra closure of type_check_internal"); - cx.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output); - liveness::generate( - &mut cx, - body, - elements, - flow_inits, - move_data, - location_table, - use_polonius, - ); - - translate_outlives_facts(&mut cx); - let opaque_type_values = - infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); - - opaque_type_values - .into_iter() - .map(|(opaque_type_key, decl)| { - cx.fully_perform_op( - Locations::All(body.span), - ConstraintCategory::OpaqueType, - CustomTypeOp::new( - |infcx| { - infcx.register_member_constraints( - param_env, - opaque_type_key, - decl.hidden_type.ty, - decl.hidden_type.span, - ); - Ok(InferOk { value: (), obligations: vec![] }) - }, - || "opaque_type_map".to_string(), - ), - ) - .unwrap(); - let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type); - trace!( - "finalized opaque type {:?} to {:#?}", - opaque_type_key, - hidden_type.ty.kind() - ); - if hidden_type.has_infer_types_or_consts() { - infcx.tcx.sess.delay_span_bug( - decl.hidden_type.span, - &format!("could not resolve {:#?}", hidden_type.ty.kind()), - ); - hidden_type.ty = infcx.tcx.ty_error(); - } - - (opaque_type_key, (hidden_type, decl.origin)) - }) - .collect() - }, ); - MirTypeckResults { constraints, universal_region_relations, opaque_type_values } -} - -#[instrument( - skip(infcx, body, promoted, region_bound_pairs, borrowck_context, extra), - level = "debug" -)] -fn type_check_internal<'a, 'tcx, R>( - infcx: &'a InferCtxt<'a, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - body: &'a Body<'tcx>, - promoted: &'a IndexVec>, - region_bound_pairs: &'a RegionBoundPairs<'tcx>, - implicit_region_bound: ty::Region<'tcx>, - borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, - extra: impl FnOnce(TypeChecker<'a, 'tcx>) -> R, -) -> R { - debug!("body: {:#?}", body); - let mut checker = TypeChecker::new( - infcx, - body, - param_env, - region_bound_pairs, - implicit_region_bound, - borrowck_context, - ); let errors_reported = { let mut verifier = TypeVerifier::new(&mut checker, promoted); verifier.visit_body(&body); @@ -280,7 +198,56 @@ fn type_check_internal<'a, 'tcx, R>( checker.typeck_mir(body); } - extra(checker) + checker.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output); + liveness::generate( + &mut checker, + body, + elements, + flow_inits, + move_data, + location_table, + use_polonius, + ); + + translate_outlives_facts(&mut checker); + let opaque_type_values = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); + + let opaque_type_values = opaque_type_values + .into_iter() + .map(|(opaque_type_key, decl)| { + checker + .fully_perform_op( + Locations::All(body.span), + ConstraintCategory::OpaqueType, + CustomTypeOp::new( + |infcx| { + infcx.register_member_constraints( + param_env, + opaque_type_key, + decl.hidden_type.ty, + decl.hidden_type.span, + ); + Ok(InferOk { value: (), obligations: vec![] }) + }, + || "opaque_type_map".to_string(), + ), + ) + .unwrap(); + let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type); + trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind()); + if hidden_type.has_infer_types_or_consts() { + infcx.tcx.sess.delay_span_bug( + decl.hidden_type.span, + &format!("could not resolve {:#?}", hidden_type.ty.kind()), + ); + hidden_type.ty = infcx.tcx.ty_error(); + } + + (opaque_type_key, (hidden_type, decl.origin)) + }) + .collect(); + + MirTypeckResults { constraints, universal_region_relations, opaque_type_values } } fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) { From 07e41fb54c3d06afb1c100e945f2eae2233ff270 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Fri, 19 Aug 2022 14:37:53 +0000 Subject: [PATCH 07/22] update test for LLVM change LLVM commit https://github.com/llvm/llvm-project/commit/c2a38887932e3a46aa3bee35f3f5568ac68282f4 updates the PIC level version selection. This updates the rust tests to work under both the old and new behaviors. Detected by our experimental rust + llvm @ HEAD bot: https://buildkite.com/llvm-project/rust-llvm-integrate-prototype/builds/12829#0182b368-a405-47a2-b3da-9c79cb907bfe/701-709 --- src/test/codegen/pic-relocation-model.rs | 2 +- src/test/codegen/pie-relocation-model.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/codegen/pic-relocation-model.rs b/src/test/codegen/pic-relocation-model.rs index 6e1d5a6c3f271..bcfe2f9af50bd 100644 --- a/src/test/codegen/pic-relocation-model.rs +++ b/src/test/codegen/pic-relocation-model.rs @@ -13,4 +13,4 @@ pub fn call_foreign_fn() -> u8 { // CHECK: declare zeroext i8 @foreign_fn() extern "C" {fn foreign_fn() -> u8;} -// CHECK: !{i32 7, !"PIC Level", i32 2} +// CHECK: !{i32 {{[78]}}, !"PIC Level", i32 2} diff --git a/src/test/codegen/pie-relocation-model.rs b/src/test/codegen/pie-relocation-model.rs index a843202a94f82..ec44edc066774 100644 --- a/src/test/codegen/pie-relocation-model.rs +++ b/src/test/codegen/pie-relocation-model.rs @@ -18,5 +18,5 @@ pub fn call_foreign_fn() -> u8 { // CHECK: declare zeroext i8 @foreign_fn() extern "C" {fn foreign_fn() -> u8;} -// CHECK: !{i32 7, !"PIC Level", i32 2} +// CHECK: !{i32 {{[78]}}, !"PIC Level", i32 2} // CHECK: !{i32 7, !"PIE Level", i32 2} From 8b7b1f773a4d97b9567eb5998b5e59a718ece9d7 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Wed, 17 Aug 2022 13:07:17 -0700 Subject: [PATCH 08/22] Minor syntax and formatting update to doc comment The comment is on find_vtable_types_for_unsizing, but there is another unrelated typo fix as well. --- compiler/rustc_monomorphize/src/collector.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 96bbf5802e738..82ef16a7f72fc 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -128,7 +128,7 @@ //! #### Unsizing Casts //! A subtle way of introducing neighbor edges is by casting to a trait object. //! Since the resulting fat-pointer contains a reference to a vtable, we need to -//! instantiate all object-save methods of the trait, as we need to store +//! instantiate all object-safe methods of the trait, as we need to store //! pointers to these functions even if they never get called anywhere. This can //! be seen as a special case of taking a function reference. //! @@ -1044,10 +1044,12 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> /// them. /// /// For example, the source type might be `&SomeStruct` and the target type -/// might be `&SomeTrait` in a cast like: +/// might be `&dyn SomeTrait` in a cast like: /// +/// ```rust,ignore (not real code) /// let src: &SomeStruct = ...; -/// let target = src as &SomeTrait; +/// let target = src as &dyn SomeTrait; +/// ``` /// /// Then the output of this function would be (SomeStruct, SomeTrait) since for /// constructing the `target` fat-pointer we need the vtable for that pair. @@ -1068,8 +1070,10 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> /// for the pair of `T` (which is a trait) and the concrete type that `T` was /// originally coerced from: /// +/// ```rust,ignore (not real code) /// let src: &ComplexStruct = ...; -/// let target = src as &ComplexStruct; +/// let target = src as &ComplexStruct; +/// ``` /// /// Again, we want this `find_vtable_types_for_unsizing()` to provide the pair /// `(SomeStruct, SomeTrait)`. From f506656876d445eb64c00721ca39007d08480e65 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Fri, 19 Aug 2022 16:02:48 -0700 Subject: [PATCH 09/22] Align android `sigaddset` impl with the reference impl from Bionic --- .../src/sys/unix/process/process_common.rs | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index bca1b65a7fc05..6ef02e2df775b 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -45,11 +45,31 @@ cfg_if::cfg_if! { } #[allow(dead_code)] pub unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int { - use crate::{slice, mem}; + use crate::{ + mem::{align_of, size_of}, + slice, + }; + use libc::{c_ulong, sigset_t}; + + // The implementations from bionic (android libc) type pun `sigset_t` as an + // array of `c_ulong`. This works, but lets add a smoke check to make sure + // that doesn't change. + const _: () = assert!( + align_of::() == align_of::() + && (size_of::() % size_of::()) == 0 + ); - let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::()); let bit = (signum - 1) as usize; - raw[bit / 8] |= 1 << (bit % 8); + if set.is_null() || bit < 0 || bit >= (8 * size_of::()) { + crate::sys::unix::os::set_errno(libc::EINVAL); + return -1; + } + let raw = slice::from_raw_parts_mut( + set as *mut c_ulong, + size_of::() / size_of::(), + ); + const LONG_BIT: usize = size_of::() * 8; + raw[bit / LONG_BIT] |= 1 << (bit % LONG_BIT); return 0; } } else { From ae2b1dbc8915c2a41bc3555cceb65a07c0032b05 Mon Sep 17 00:00:00 2001 From: ltdk Date: Fri, 19 Aug 2022 20:38:32 -0400 Subject: [PATCH 10/22] Tracking issue for const_reverse --- library/core/src/slice/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 361862cdd5257..75c7c4d5581d9 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -674,7 +674,7 @@ impl [T] { /// assert!(v == [3, 2, 1]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_reverse", issue = "none")] + #[rustc_const_unstable(feature = "const_reverse", issue = "100784")] #[inline] pub const fn reverse(&mut self) { let half_len = self.len() / 2; From 042e0d02d74862796e9716abee07455b5e885151 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 19 Aug 2022 17:27:22 +0200 Subject: [PATCH 11/22] Merge "EnterSpan" events to reduce code blocks DOM size --- src/librustdoc/html/highlight.rs | 91 ++++++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 23 deletions(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 944cf08851240..562a5933025f2 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -141,7 +141,7 @@ fn write_pending_elems( if !done { // We only want to "open" the tag ourselves if we have more than one pending and if the current // parent tag is not the same as our pending content. - let open_tag_ourselves = pending_elems.len() > 1; + let open_tag_ourselves = pending_elems.len() > 1 && current_class.is_some(); let close_tag = if open_tag_ourselves { enter_span(out, current_class.unwrap(), &href_context) } else { @@ -158,6 +158,18 @@ fn write_pending_elems( *current_class = None; } +fn handle_exit_span( + out: &mut Buffer, + href_context: &Option>, + pending_elems: &mut Vec<(&str, Option)>, + closing_tags: &mut Vec<(&str, Class)>, +) { + let class = closing_tags.last().expect("ExitSpan without EnterSpan").1; + // We flush everything just in case... + write_pending_elems(out, href_context, pending_elems, &mut Some(class), closing_tags); + exit_span(out, closing_tags.pop().expect("ExitSpan without EnterSpan").0); +} + /// Check if two `Class` can be merged together. In the following rules, "unclassified" means `None` /// basically (since it's `Option`). The following rules apply: /// @@ -171,7 +183,7 @@ fn can_merge(class1: Option, class2: Option, text: &str) -> bool { (Some(c1), Some(c2)) => c1.is_equal_to(c2), (Some(Class::Ident(_)), None) | (None, Some(Class::Ident(_))) => true, (Some(_), None) | (None, Some(_)) => text.trim().is_empty(), - _ => false, + (None, None) => true, } } @@ -196,6 +208,9 @@ fn write_code( let src = src.replace("\r\n", "\n"); // It contains the closing tag and the associated `Class`. let mut closing_tags: Vec<(&'static str, Class)> = Vec::new(); + // This is used because we don't automatically generate the closing tag on `ExitSpan` in + // case an `EnterSpan` event with the same class follows. + let mut pending_exit_span: Option = None; // The following two variables are used to group HTML elements with same `class` attributes // to reduce the DOM size. let mut current_class: Option = None; @@ -211,9 +226,21 @@ fn write_code( .highlight(&mut |highlight| { match highlight { Highlight::Token { text, class } => { + // If we received a `ExitSpan` event and then have a non-compatible `Class`, we + // need to close the ``. + if let Some(pending) = pending_exit_span && + !can_merge(Some(pending), class, text) { + handle_exit_span( + out, + &href_context, + &mut pending_elems, + &mut closing_tags, + ); + pending_exit_span = None; + current_class = class.map(Class::dummy); // If the two `Class` are different, time to flush the current content and start // a new one. - if !can_merge(current_class, class, text) { + } else if !can_merge(current_class, class, text) { write_pending_elems( out, &href_context, @@ -228,30 +255,48 @@ fn write_code( pending_elems.push((text, class)); } Highlight::EnterSpan { class } => { - // We flush everything just in case... - write_pending_elems( - out, - &href_context, - &mut pending_elems, - &mut current_class, - &closing_tags, - ); - closing_tags.push((enter_span(out, class, &href_context), class)) + let mut should_add = true; + if pending_exit_span.is_some() { + if !can_merge(Some(class), pending_exit_span, "") { + handle_exit_span(out, &href_context, &mut pending_elems, &mut closing_tags); + } else { + should_add = false; + } + } else { + // We flush everything just in case... + write_pending_elems( + out, + &href_context, + &mut pending_elems, + &mut current_class, + &closing_tags, + ); + } + current_class = None; + pending_exit_span = None; + if should_add { + let closing_tag = enter_span(out, class, &href_context); + closing_tags.push((closing_tag, class)); + } } Highlight::ExitSpan => { - // We flush everything just in case... - write_pending_elems( - out, - &href_context, - &mut pending_elems, - &mut current_class, - &closing_tags, - ); - exit_span(out, closing_tags.pop().expect("ExitSpan without EnterSpan").0) + current_class = None; + pending_exit_span = + Some(closing_tags.last().as_ref().expect("ExitSpan without EnterSpan").1); } }; }); - write_pending_elems(out, &href_context, &mut pending_elems, &mut current_class, &closing_tags); + if pending_exit_span.is_some() { + handle_exit_span(out, &href_context, &mut pending_elems, &mut closing_tags); + } else { + write_pending_elems( + out, + &href_context, + &mut pending_elems, + &mut current_class, + &closing_tags, + ); + } } fn write_footer(out: &mut Buffer, playground_button: Option<&str>) { @@ -761,7 +806,7 @@ impl<'a> Classifier<'a> { TokenKind::CloseBracket => { if self.in_attribute { self.in_attribute = false; - sink(Highlight::Token { text: "]", class: Some(Class::Attribute) }); + sink(Highlight::Token { text: "]", class: None }); sink(Highlight::ExitSpan); return; } From f5b5d867d5954c2a843f6a3db338ea86fafd66b1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 19 Aug 2022 18:16:02 +0200 Subject: [PATCH 12/22] Update rustdoc tests --- .../html/highlight/fixtures/decorations.html | 4 ++-- .../html/highlight/fixtures/sample.html | 15 ++++++++------- src/librustdoc/html/highlight/fixtures/sample.rs | 1 + src/test/rustdoc/issue-41783.codeblock.html | 4 ++-- src/test/rustdoc/issue-41783.rs | 6 ++++-- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/html/highlight/fixtures/decorations.html b/src/librustdoc/html/highlight/fixtures/decorations.html index 2184897872153..f73e7c1fe7697 100644 --- a/src/librustdoc/html/highlight/fixtures/decorations.html +++ b/src/librustdoc/html/highlight/fixtures/decorations.html @@ -1,2 +1,2 @@ -let x = 1; -let y = 2; \ No newline at end of file +let x = 1; +let y = 2; \ No newline at end of file diff --git a/src/librustdoc/html/highlight/fixtures/sample.html b/src/librustdoc/html/highlight/fixtures/sample.html index ae2650528eb72..4a5a3cf609cd4 100644 --- a/src/librustdoc/html/highlight/fixtures/sample.html +++ b/src/librustdoc/html/highlight/fixtures/sample.html @@ -8,12 +8,13 @@ .lifetime { color: #B76514; } .question-mark { color: #ff9011; } -
#![crate_type = "lib"]
+
#![crate_type = "lib"]
 
-use std::path::{Path, PathBuf};
+use std::path::{Path, PathBuf};
 
-#[cfg(target_os = "linux")]
-fn main() -> () {
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "windows")]
+fn main() -> () {
     let foo = true && false || true;
     let _: *const () = 0;
     let _ = &foo;
@@ -22,8 +23,8 @@
     mac!(foo, &mut bar);
     assert!(self.length < N && index <= self.length);
     ::std::env::var("gateau").is_ok();
-    #[rustfmt::skip]
-    let s:std::path::PathBuf = std::path::PathBuf::new();
+    #[rustfmt::skip]
+    let s:std::path::PathBuf = std::path::PathBuf::new();
     let mut s = String::new();
 
     match &s {
@@ -31,7 +32,7 @@
     }
 }
 
-macro_rules! bar {
+macro_rules! bar {
     ($foo:tt) => {};
 }
 
diff --git a/src/librustdoc/html/highlight/fixtures/sample.rs b/src/librustdoc/html/highlight/fixtures/sample.rs index fbfdc6767337c..ef85b566cb3c4 100644 --- a/src/librustdoc/html/highlight/fixtures/sample.rs +++ b/src/librustdoc/html/highlight/fixtures/sample.rs @@ -3,6 +3,7 @@ use std::path::{Path, PathBuf}; #[cfg(target_os = "linux")] +#[cfg(target_os = "windows")] fn main() -> () { let foo = true && false || true; let _: *const () = 0; diff --git a/src/test/rustdoc/issue-41783.codeblock.html b/src/test/rustdoc/issue-41783.codeblock.html index b919935e4b47a..89987491d1b46 100644 --- a/src/test/rustdoc/issue-41783.codeblock.html +++ b/src/test/rustdoc/issue-41783.codeblock.html @@ -1,5 +1,5 @@ # single ## double ### triple -#[outer] -#![inner] \ No newline at end of file +#[outer] +#![inner]
diff --git a/src/test/rustdoc/issue-41783.rs b/src/test/rustdoc/issue-41783.rs index d67716028799b..87267a750c615 100644 --- a/src/test/rustdoc/issue-41783.rs +++ b/src/test/rustdoc/issue-41783.rs @@ -1,8 +1,10 @@ // @has issue_41783/struct.Foo.html // @!hasraw - 'space' // @!hasraw - 'comment' -// @hasraw - '#[outer]' -// @hasraw - '#![inner]' +// @hasraw - '#[outer]' +// @!hasraw - '#[outer]' +// @hasraw - '#![inner]' +// @!hasraw - '#![inner]' // @snapshot 'codeblock' - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]//pre/code' /// ```no_run From 4c89c2886d9d915db3e11a9f87a188cada9dd457 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 19 Aug 2022 21:35:09 +0200 Subject: [PATCH 13/22] Clean up highlight `` merge code --- src/librustdoc/html/highlight.rs | 239 +++++++++++++++---------------- 1 file changed, 118 insertions(+), 121 deletions(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 562a5933025f2..4a12d74ddef5a 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -111,65 +111,6 @@ fn write_header(out: &mut Buffer, class: &str, extra_content: Option) { write!(out, ""); } -/// Write all the pending elements sharing a same (or at mergeable) `Class`. -/// -/// If there is a "parent" (if a `EnterSpan` event was encountered) and the parent can be merged -/// with the elements' class, then we simply write the elements since the `ExitSpan` event will -/// close the tag. -/// -/// Otherwise, if there is only one pending element, we let the `string` function handle both -/// opening and closing the tag, otherwise we do it into this function. -fn write_pending_elems( - out: &mut Buffer, - href_context: &Option>, - pending_elems: &mut Vec<(&str, Option)>, - current_class: &mut Option, - closing_tags: &[(&str, Class)], -) { - if pending_elems.is_empty() { - return; - } - let mut done = false; - if let Some((_, parent_class)) = closing_tags.last() { - if can_merge(*current_class, Some(*parent_class), "") { - for (text, class) in pending_elems.iter() { - string(out, Escape(text), *class, &href_context, false); - } - done = true; - } - } - if !done { - // We only want to "open" the tag ourselves if we have more than one pending and if the current - // parent tag is not the same as our pending content. - let open_tag_ourselves = pending_elems.len() > 1 && current_class.is_some(); - let close_tag = if open_tag_ourselves { - enter_span(out, current_class.unwrap(), &href_context) - } else { - "" - }; - for (text, class) in pending_elems.iter() { - string(out, Escape(text), *class, &href_context, !open_tag_ourselves); - } - if open_tag_ourselves { - exit_span(out, close_tag); - } - } - pending_elems.clear(); - *current_class = None; -} - -fn handle_exit_span( - out: &mut Buffer, - href_context: &Option>, - pending_elems: &mut Vec<(&str, Option)>, - closing_tags: &mut Vec<(&str, Class)>, -) { - let class = closing_tags.last().expect("ExitSpan without EnterSpan").1; - // We flush everything just in case... - write_pending_elems(out, href_context, pending_elems, &mut Some(class), closing_tags); - exit_span(out, closing_tags.pop().expect("ExitSpan without EnterSpan").0); -} - /// Check if two `Class` can be merged together. In the following rules, "unclassified" means `None` /// basically (since it's `Option`). The following rules apply: /// @@ -187,6 +128,87 @@ fn can_merge(class1: Option, class2: Option, text: &str) -> bool { } } +/// This type is used as a conveniency to prevent having to pass all its fields as arguments into +/// the various functions (which became its methods). +struct TokenHandler<'a, 'b, 'c, 'd, 'e> { + out: &'a mut Buffer, + /// It contains the closing tag and the associated `Class`. + closing_tags: Vec<(&'static str, Class)>, + /// This is used because we don't automatically generate the closing tag on `ExitSpan` in + /// case an `EnterSpan` event with the same class follows. + pending_exit_span: Option, + /// `current_class` and `pending_elems` are used to group HTML elements with same `class` + /// attributes to reduce the DOM size. + current_class: Option, + /// We need to keep the `Class` for each element because it could contain a `Span` which is + /// used to generate links. + pending_elems: Vec<(&'b str, Option)>, + href_context: Option>, +} + +impl<'a, 'b, 'c, 'd, 'e> TokenHandler<'a, 'b, 'c, 'd, 'e> { + fn handle_exit_span(&mut self) { + // We can't get the last `closing_tags` element using `pop()` because `closing_tags` is + // being used in `write_pending_elems`. + let class = self.closing_tags.last().expect("ExitSpan without EnterSpan").1; + // We flush everything just in case... + self.write_pending_elems(Some(class)); + + exit_span(self.out, self.closing_tags.pop().expect("ExitSpan without EnterSpan").0); + self.pending_exit_span = None; + } + + /// Write all the pending elements sharing a same (or at mergeable) `Class`. + /// + /// If there is a "parent" (if a `EnterSpan` event was encountered) and the parent can be merged + /// with the elements' class, then we simply write the elements since the `ExitSpan` event will + /// close the tag. + /// + /// Otherwise, if there is only one pending element, we let the `string` function handle both + /// opening and closing the tag, otherwise we do it into this function. + /// + /// It returns `true` if `current_class` must be set to `None` afterwards. + fn write_pending_elems(&mut self, current_class: Option) -> bool { + if self.pending_elems.is_empty() { + return false; + } + if let Some((_, parent_class)) = self.closing_tags.last() && + can_merge(current_class, Some(*parent_class), "") + { + for (text, class) in self.pending_elems.iter() { + string(self.out, Escape(text), *class, &self.href_context, false); + } + } else { + // We only want to "open" the tag ourselves if we have more than one pending and if the + // current parent tag is not the same as our pending content. + let close_tag = if self.pending_elems.len() > 1 && current_class.is_some() { + Some(enter_span(self.out, current_class.unwrap(), &self.href_context)) + } else { + None + }; + for (text, class) in self.pending_elems.iter() { + string(self.out, Escape(text), *class, &self.href_context, close_tag.is_none()); + } + if let Some(close_tag) = close_tag { + exit_span(self.out, close_tag); + } + } + self.pending_elems.clear(); + true + } +} + +impl<'a, 'b, 'c, 'd, 'e> Drop for TokenHandler<'a, 'b, 'c, 'd, 'e> { + /// When leaving, we need to flush all pending data to not have missing content. + fn drop(&mut self) { + if self.pending_exit_span.is_some() { + self.handle_exit_span(); + } else { + self.write_pending_elems(self.current_class); + } + } +} + /// Convert the given `src` source code into HTML by adding classes for highlighting. /// /// This code is used to render code blocks (in the documentation) as well as the source code pages. @@ -206,21 +228,18 @@ fn write_code( ) { // This replace allows to fix how the code source with DOS backline characters is displayed. let src = src.replace("\r\n", "\n"); - // It contains the closing tag and the associated `Class`. - let mut closing_tags: Vec<(&'static str, Class)> = Vec::new(); - // This is used because we don't automatically generate the closing tag on `ExitSpan` in - // case an `EnterSpan` event with the same class follows. - let mut pending_exit_span: Option = None; - // The following two variables are used to group HTML elements with same `class` attributes - // to reduce the DOM size. - let mut current_class: Option = None; - // We need to keep the `Class` for each element because it could contain a `Span` which is - // used to generate links. - let mut pending_elems: Vec<(&str, Option)> = Vec::new(); + let mut token_handler = TokenHandler { + out, + closing_tags: Vec::new(), + pending_exit_span: None, + current_class: None, + pending_elems: Vec::new(), + href_context, + }; Classifier::new( &src, - href_context.as_ref().map(|c| c.file_span).unwrap_or(DUMMY_SP), + token_handler.href_context.as_ref().map(|c| c.file_span).unwrap_or(DUMMY_SP), decoration_info, ) .highlight(&mut |highlight| { @@ -228,75 +247,53 @@ fn write_code( Highlight::Token { text, class } => { // If we received a `ExitSpan` event and then have a non-compatible `Class`, we // need to close the ``. - if let Some(pending) = pending_exit_span && + let need_current_class_update = if let Some(pending) = token_handler.pending_exit_span && !can_merge(Some(pending), class, text) { - handle_exit_span( - out, - &href_context, - &mut pending_elems, - &mut closing_tags, - ); - pending_exit_span = None; - current_class = class.map(Class::dummy); + token_handler.handle_exit_span(); + true // If the two `Class` are different, time to flush the current content and start // a new one. - } else if !can_merge(current_class, class, text) { - write_pending_elems( - out, - &href_context, - &mut pending_elems, - &mut current_class, - &closing_tags, - ); - current_class = class.map(Class::dummy); - } else if current_class.is_none() { - current_class = class.map(Class::dummy); + } else if !can_merge(token_handler.current_class, class, text) { + token_handler.write_pending_elems(token_handler.current_class); + true + } else { + token_handler.current_class.is_none() + }; + + if need_current_class_update { + token_handler.current_class = class.map(Class::dummy); } - pending_elems.push((text, class)); + token_handler.pending_elems.push((text, class)); } Highlight::EnterSpan { class } => { let mut should_add = true; - if pending_exit_span.is_some() { - if !can_merge(Some(class), pending_exit_span, "") { - handle_exit_span(out, &href_context, &mut pending_elems, &mut closing_tags); - } else { + if let Some(pending_exit_span) = token_handler.pending_exit_span { + if class.is_equal_to(pending_exit_span) { should_add = false; + } else { + token_handler.handle_exit_span(); } } else { // We flush everything just in case... - write_pending_elems( - out, - &href_context, - &mut pending_elems, - &mut current_class, - &closing_tags, - ); + if token_handler.write_pending_elems(token_handler.current_class) { + token_handler.current_class = None; + } } - current_class = None; - pending_exit_span = None; if should_add { - let closing_tag = enter_span(out, class, &href_context); - closing_tags.push((closing_tag, class)); + let closing_tag = enter_span(token_handler.out, class, &token_handler.href_context); + token_handler.closing_tags.push((closing_tag, class)); } + + token_handler.current_class = None; + token_handler.pending_exit_span = None; } Highlight::ExitSpan => { - current_class = None; - pending_exit_span = - Some(closing_tags.last().as_ref().expect("ExitSpan without EnterSpan").1); + token_handler.current_class = None; + token_handler.pending_exit_span = + Some(token_handler.closing_tags.last().as_ref().expect("ExitSpan without EnterSpan").1); } }; }); - if pending_exit_span.is_some() { - handle_exit_span(out, &href_context, &mut pending_elems, &mut closing_tags); - } else { - write_pending_elems( - out, - &href_context, - &mut pending_elems, - &mut current_class, - &closing_tags, - ); - } } fn write_footer(out: &mut Buffer, playground_button: Option<&str>) { From 7ab8e0cbe4c6e7617fe43a44467c463fad3b010e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 20 Aug 2022 14:24:05 +0200 Subject: [PATCH 14/22] Extend decoration test to detect regressions --- src/librustdoc/html/highlight/fixtures/decorations.html | 4 +++- src/librustdoc/html/highlight/tests.rs | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/highlight/fixtures/decorations.html b/src/librustdoc/html/highlight/fixtures/decorations.html index f73e7c1fe7697..ebf29f9cb3a91 100644 --- a/src/librustdoc/html/highlight/fixtures/decorations.html +++ b/src/librustdoc/html/highlight/fixtures/decorations.html @@ -1,2 +1,4 @@ let x = 1; -let y = 2; \ No newline at end of file +let y = 2; +let z = 3; +let a = 4; \ No newline at end of file diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs index 4861a8ad32da6..a5e633df43448 100644 --- a/src/librustdoc/html/highlight/tests.rs +++ b/src/librustdoc/html/highlight/tests.rs @@ -69,9 +69,12 @@ fn test_union_highlighting() { fn test_decorations() { create_default_session_globals_then(|| { let src = "let x = 1; -let y = 2;"; +let y = 2; +let z = 3; +let a = 4;"; let mut decorations = FxHashMap::default(); - decorations.insert("example", vec![(0, 10)]); + decorations.insert("example", vec![(0, 10), (11, 21)]); + decorations.insert("example2", vec![(22, 32)]); let mut html = Buffer::new(); write_code(&mut html, src, None, Some(DecorationInfo(decorations))); From 0c3ed968a2117dcd532abf8ed58a8ce49a7bc742 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 20 Aug 2022 21:07:13 +0200 Subject: [PATCH 15/22] Add `/build-rust-analyzer/` to .gitignore To avoid rust-analyzer and rustc having to wait for each other, the dev guide mentions using another build directory for RA. We should also put this into the .gitignore, just like the normal `build`. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a6625ac2ac4a1..b16fb6341c2e5 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,7 @@ no_llvm_build /llvm/ /mingw-build/ /build/ +/build-rust-analyzer/ /dist/ /unicode-downloads /target From 03146471b58be8a0f9133064ea503252e60f7466 Mon Sep 17 00:00:00 2001 From: scottmcm Date: Sat, 20 Aug 2022 21:08:56 +0000 Subject: [PATCH 16/22] Allow other directives before the `ret` --- src/test/assembly/x86_64-floating-point-clamp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/assembly/x86_64-floating-point-clamp.rs b/src/test/assembly/x86_64-floating-point-clamp.rs index 4493791a5769f..0f3b465d08d4f 100644 --- a/src/test/assembly/x86_64-floating-point-clamp.rs +++ b/src/test/assembly/x86_64-floating-point-clamp.rs @@ -20,6 +20,6 @@ pub fn clamp12_demo(a: f32) -> f32 { // CHECK-NEXT: maxss xmm1, xmm0 // CHECK-NEXT: movss xmm0 // CHECK-NEXT: minss xmm0, xmm1 - // CHECK-NEXT: ret + // CHECK: ret a.clamp(1.0, 2.0) } From ed084ba292609da9fe05808f186b72453013c094 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 19 Aug 2022 13:23:00 +0400 Subject: [PATCH 17/22] Remove useless pointer cast --- library/alloc/src/vec/into_iter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 1b483e3fc7793..606e32446268b 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -148,7 +148,7 @@ impl Iterator for IntoIter { #[inline] fn next(&mut self) -> Option { - if self.ptr as *const _ == self.end { + if self.ptr == self.end { None } else if mem::size_of::() == 0 { // purposefully don't use 'ptr.offset' because for From de9da0ba8f6627e3aef4c01a95587041867e4625 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 19 Aug 2022 13:26:37 +0400 Subject: [PATCH 18/22] Make use of `pointer::is_aligned[_to]` --- library/alloc/tests/lib.rs | 1 + library/alloc/tests/thin_box.rs | 8 ++++---- library/core/src/intrinsics.rs | 2 +- library/std/src/sys/sgx/abi/usercalls/alloc.rs | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index d83cd29ddbad9..99bfb2a45ed90 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -38,6 +38,7 @@ #![feature(const_str_from_utf8)] #![feature(nonnull_slice_from_raw_parts)] #![feature(panic_update_hook)] +#![feature(pointer_is_aligned)] #![feature(slice_flatten)] #![feature(thin_box)] #![feature(bench_black_box)] diff --git a/library/alloc/tests/thin_box.rs b/library/alloc/tests/thin_box.rs index 368aa564f9436..e008b0cc35718 100644 --- a/library/alloc/tests/thin_box.rs +++ b/library/alloc/tests/thin_box.rs @@ -48,11 +48,11 @@ fn verify_aligned(ptr: *const T) { // practice these checks are mostly just smoke-detectors for an extremely // broken `ThinBox` impl, since it's an extremely subtle piece of code. let ptr = core::hint::black_box(ptr); - let align = core::mem::align_of::(); assert!( - (ptr.addr() & (align - 1)) == 0 && !ptr.is_null(), - "misaligned ThinBox data; valid pointers to `{}` should be aligned to {align}: {ptr:p}", - core::any::type_name::(), + ptr.is_aligned() && !ptr.is_null(), + "misaligned ThinBox data; valid pointers to `{ty}` should be aligned to {align}: {ptr:p}", + ty = core::any::type_name::(), + align = core::mem::align_of::(), ); } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 15467e0191dbf..5cae6da9a567b 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2139,7 +2139,7 @@ pub(crate) use assert_unsafe_precondition; /// Checks whether `ptr` is properly aligned with respect to /// `align_of::()`. pub(crate) fn is_aligned_and_not_null(ptr: *const T) -> bool { - !ptr.is_null() && ptr.addr() % mem::align_of::() == 0 + !ptr.is_null() && ptr.is_aligned() } /// Checks whether the regions of memory starting at `src` and `dst` of size diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index 66fa1efbf103f..a2c8ab7f38d54 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -115,7 +115,7 @@ pub unsafe trait UserSafe { /// * the pointer is null. /// * the pointed-to range is not in user memory. unsafe fn check_ptr(ptr: *const Self) { - let is_aligned = |p: *const u8| -> bool { 0 == p.addr() & (Self::align_of() - 1) }; + let is_aligned = |p: *const u8| -> bool { p.is_aligned_to(Self::align_of()) }; assert!(is_aligned(ptr as *const u8)); assert!(is_user_range(ptr as _, mem::size_of_val(unsafe { &*ptr }))); @@ -367,7 +367,7 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) unsafe { copy_bytewise_to_userspace(src, dst, len); } - } else if len % 8 == 0 && dst as usize % 8 == 0 { + } else if len % 8 == 0 && dst.is_aligned_to(8) { // Copying 8-byte aligned quadwords: copy quad word per quad word unsafe { copy_aligned_quadwords_to_userspace(src, dst, len); From e4720e1cf26b6a9804615f79dc6ff1a006399cf1 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 19 Aug 2022 13:33:06 +0400 Subject: [PATCH 19/22] Replace most uses of `pointer::offset` with `add` and `sub` --- compiler/rustc_arena/src/lib.rs | 2 +- .../example/alloc_system.rs | 2 +- .../rustc_codegen_gcc/example/alloc_system.rs | 2 +- compiler/rustc_serialize/src/serialize.rs | 2 +- library/alloc/src/alloc/tests.rs | 2 +- .../alloc/src/collections/vec_deque/mod.rs | 4 +-- library/alloc/src/slice.rs | 6 ++-- library/alloc/src/vec/in_place_collect.rs | 2 +- library/alloc/src/vec/into_iter.rs | 6 ++-- library/alloc/src/vec/mod.rs | 6 ++-- library/alloc/src/vec/spec_extend.rs | 2 +- library/alloc/tests/str.rs | 10 +++--- library/core/src/slice/mod.rs | 2 +- library/core/src/slice/sort.rs | 36 +++++++++---------- library/core/src/str/validations.rs | 4 +-- library/panic_abort/src/android.rs | 2 +- library/panic_unwind/src/dwarf/eh.rs | 2 +- library/std/src/os/unix/net/addr.rs | 2 +- .../std/src/sys/sgx/abi/usercalls/tests.rs | 4 +-- library/std/src/sys/windows/alloc.rs | 4 +-- library/std/src/sys/windows/fs.rs | 6 ++-- library/std/src/sys/windows/os.rs | 6 ++-- 22 files changed, 57 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 6529f11100d2d..daf67217e64a2 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -217,7 +217,7 @@ impl TypedArena { } else { let ptr = self.ptr.get(); // Advance the pointer. - self.ptr.set(self.ptr.get().offset(1)); + self.ptr.set(self.ptr.get().add(1)); // Write into uninitialized memory. ptr::write(ptr, object); &mut *ptr diff --git a/compiler/rustc_codegen_cranelift/example/alloc_system.rs b/compiler/rustc_codegen_cranelift/example/alloc_system.rs index cf95c89bc3156..50261c1939739 100644 --- a/compiler/rustc_codegen_cranelift/example/alloc_system.rs +++ b/compiler/rustc_codegen_cranelift/example/alloc_system.rs @@ -94,7 +94,7 @@ mod platform { struct Header(*mut u8); const HEAP_ZERO_MEMORY: DWORD = 0x00000008; unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header { - &mut *(ptr as *mut Header).offset(-1) + &mut *(ptr as *mut Header).sub(1) } unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 { let aligned = ptr.add(align - (ptr as usize & (align - 1))); diff --git a/compiler/rustc_codegen_gcc/example/alloc_system.rs b/compiler/rustc_codegen_gcc/example/alloc_system.rs index 5f66ca67f2d40..89661918d05a5 100644 --- a/compiler/rustc_codegen_gcc/example/alloc_system.rs +++ b/compiler/rustc_codegen_gcc/example/alloc_system.rs @@ -156,7 +156,7 @@ mod platform { struct Header(*mut u8); const HEAP_ZERO_MEMORY: DWORD = 0x00000008; unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header { - &mut *(ptr as *mut Header).offset(-1) + &mut *(ptr as *mut Header).sub(1) } unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 { let aligned = ptr.add(align - (ptr as usize & (align - 1))); diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 36585b8d77e0a..9bd5550038fc6 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -273,7 +273,7 @@ impl> Decodable for Vec { unsafe { let ptr: *mut T = vec.as_mut_ptr(); for i in 0..len { - std::ptr::write(ptr.offset(i as isize), Decodable::decode(d)); + std::ptr::write(ptr.add(i), Decodable::decode(d)); } vec.set_len(len); } diff --git a/library/alloc/src/alloc/tests.rs b/library/alloc/src/alloc/tests.rs index 7d560964d85be..b2f0194599b28 100644 --- a/library/alloc/src/alloc/tests.rs +++ b/library/alloc/src/alloc/tests.rs @@ -15,7 +15,7 @@ fn allocate_zeroed() { let end = i.add(layout.size()); while i < end { assert_eq!(*i, 0); - i = i.offset(1); + i = i.add(1); } Global.deallocate(ptr.as_non_null_ptr(), layout); } diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 4d895d83745b2..57ab74e01590b 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -2447,8 +2447,8 @@ impl VecDeque { let mut right_offset = 0; for i in left_edge..right_edge { right_offset = (i - left_edge) % (cap - right_edge); - let src: isize = (right_edge + right_offset) as isize; - ptr::swap(buf.add(i), buf.offset(src)); + let src = right_edge + right_offset; + ptr::swap(buf.add(i), buf.add(src)); } let n_ops = right_edge - left_edge; left_edge += n_ops; diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 63d4d94529008..5733124ec7565 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -1024,7 +1024,7 @@ where // Consume the greater side. // If equal, prefer the right run to maintain stability. unsafe { - let to_copy = if is_less(&*right.offset(-1), &*left.offset(-1)) { + let to_copy = if is_less(&*right.sub(1), &*left.sub(1)) { decrement_and_get(left) } else { decrement_and_get(right) @@ -1038,12 +1038,12 @@ where unsafe fn get_and_increment(ptr: &mut *mut T) -> *mut T { let old = *ptr; - *ptr = unsafe { ptr.offset(1) }; + *ptr = unsafe { ptr.add(1) }; old } unsafe fn decrement_and_get(ptr: &mut *mut T) -> *mut T { - *ptr = unsafe { ptr.offset(-1) }; + *ptr = unsafe { ptr.sub(1) }; *ptr } diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index 55dcb84ad16f9..b211421b20270 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -267,7 +267,7 @@ where // one slot in the underlying storage will have been freed up and we can immediately // write back the result. unsafe { - let dst = dst_buf.offset(i as isize); + let dst = dst_buf.add(i); debug_assert!(dst as *const _ <= end, "InPlaceIterable contract violation"); ptr::write(dst, self.__iterator_get_unchecked(i)); // Since this executes user code which can panic we have to bump the pointer diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 1b483e3fc7793..e02ad391a595f 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -160,7 +160,7 @@ impl Iterator for IntoIter { Some(unsafe { mem::zeroed() }) } else { let old = self.ptr; - self.ptr = unsafe { self.ptr.offset(1) }; + self.ptr = unsafe { self.ptr.add(1) }; Some(unsafe { ptr::read(old) }) } @@ -272,7 +272,7 @@ impl DoubleEndedIterator for IntoIter { // Make up a value of this ZST. Some(unsafe { mem::zeroed() }) } else { - self.end = unsafe { self.end.offset(-1) }; + self.end = unsafe { self.end.sub(1) }; Some(unsafe { ptr::read(self.end) }) } @@ -288,7 +288,7 @@ impl DoubleEndedIterator for IntoIter { } } else { // SAFETY: same as for advance_by() - self.end = unsafe { self.end.offset(step_size.wrapping_neg() as isize) }; + self.end = unsafe { self.end.sub(step_size) }; } let to_drop = ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size); // SAFETY: same as for advance_by() diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index fa9f2131c0c1d..3251e6240d8ae 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1393,7 +1393,7 @@ impl Vec { if index < len { // Shift everything over to make space. (Duplicating the // `index`th element into two consecutive places.) - ptr::copy(p, p.offset(1), len - index); + ptr::copy(p, p.add(1), len - index); } else if index == len { // No elements need shifting. } else { @@ -1455,7 +1455,7 @@ impl Vec { ret = ptr::read(ptr); // Shift everything down to fill in that spot. - ptr::copy(ptr.offset(1), ptr, len - index - 1); + ptr::copy(ptr.add(1), ptr, len - index - 1); } self.set_len(len - 1); ret @@ -2408,7 +2408,7 @@ impl Vec { // Write all elements except the last one for _ in 1..n { ptr::write(ptr, value.next()); - ptr = ptr.offset(1); + ptr = ptr.add(1); // Increment the length in every step in case next() panics local_len.increment_len(1); } diff --git a/library/alloc/src/vec/spec_extend.rs b/library/alloc/src/vec/spec_extend.rs index 506ee0ecfa279..1ea9c827afd70 100644 --- a/library/alloc/src/vec/spec_extend.rs +++ b/library/alloc/src/vec/spec_extend.rs @@ -39,7 +39,7 @@ where let mut local_len = SetLenOnDrop::new(&mut self.len); iterator.for_each(move |element| { ptr::write(ptr, element); - ptr = ptr.offset(1); + ptr = ptr.add(1); // Since the loop executes user code which can panic we have to bump the pointer // after each step. // NB can't overflow since we would have had to alloc the address space diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs index 7379569dd68fe..e30329aa1cb6c 100644 --- a/library/alloc/tests/str.rs +++ b/library/alloc/tests/str.rs @@ -1010,11 +1010,11 @@ fn test_as_bytes_fail() { fn test_as_ptr() { let buf = "hello".as_ptr(); unsafe { - assert_eq!(*buf.offset(0), b'h'); - assert_eq!(*buf.offset(1), b'e'); - assert_eq!(*buf.offset(2), b'l'); - assert_eq!(*buf.offset(3), b'l'); - assert_eq!(*buf.offset(4), b'o'); + assert_eq!(*buf.add(0), b'h'); + assert_eq!(*buf.add(1), b'e'); + assert_eq!(*buf.add(2), b'l'); + assert_eq!(*buf.add(3), b'l'); + assert_eq!(*buf.add(4), b'o'); } } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index e79d47c9f98cd..f98a279c02f4c 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -2921,7 +2921,7 @@ impl [T] { let prev_ptr_write = ptr.add(next_write - 1); if !same_bucket(&mut *ptr_read, &mut *prev_ptr_write) { if next_read != next_write { - let ptr_write = prev_ptr_write.offset(1); + let ptr_write = prev_ptr_write.add(1); mem::swap(&mut *ptr_read, &mut *ptr_write); } next_write += 1; diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index 6a201834b8e68..8b025da2a46ed 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -326,8 +326,8 @@ where unsafe { // Branchless comparison. *end_l = i as u8; - end_l = end_l.offset(!is_less(&*elem, pivot) as isize); - elem = elem.offset(1); + end_l = end_l.add(!is_less(&*elem, pivot) as usize); + elem = elem.add(1); } } } @@ -352,9 +352,9 @@ where // Plus, `block_r` was asserted to be less than `BLOCK` and `elem` will therefore at most be pointing to the beginning of the slice. unsafe { // Branchless comparison. - elem = elem.offset(-1); + elem = elem.sub(1); *end_r = i as u8; - end_r = end_r.offset(is_less(&*elem, pivot) as isize); + end_r = end_r.add(is_less(&*elem, pivot) as usize); } } } @@ -365,12 +365,12 @@ where if count > 0 { macro_rules! left { () => { - l.offset(*start_l as isize) + l.add(*start_l as usize) }; } macro_rules! right { () => { - r.offset(-(*start_r as isize) - 1) + r.sub((*start_r as usize) + 1) }; } @@ -398,16 +398,16 @@ where ptr::copy_nonoverlapping(right!(), left!(), 1); for _ in 1..count { - start_l = start_l.offset(1); + start_l = start_l.add(1); ptr::copy_nonoverlapping(left!(), right!(), 1); - start_r = start_r.offset(1); + start_r = start_r.add(1); ptr::copy_nonoverlapping(right!(), left!(), 1); } ptr::copy_nonoverlapping(&tmp, right!(), 1); mem::forget(tmp); - start_l = start_l.offset(1); - start_r = start_r.offset(1); + start_l = start_l.add(1); + start_r = start_r.add(1); } } @@ -420,7 +420,7 @@ where // safe. Otherwise, the debug assertions in the `is_done` case guarantee that // `width(l, r) == block_l + block_r`, namely, that the block sizes have been adjusted to account // for the smaller number of remaining elements. - l = unsafe { l.offset(block_l as isize) }; + l = unsafe { l.add(block_l) }; } if start_r == end_r { @@ -428,7 +428,7 @@ where // SAFETY: Same argument as [block-width-guarantee]. Either this is a full block `2*BLOCK`-wide, // or `block_r` has been adjusted for the last handful of elements. - r = unsafe { r.offset(-(block_r as isize)) }; + r = unsafe { r.sub(block_r) }; } if is_done { @@ -457,9 +457,9 @@ where // - `offsets_l` contains valid offsets into `v` collected during the partitioning of // the last block, so the `l.offset` calls are valid. unsafe { - end_l = end_l.offset(-1); - ptr::swap(l.offset(*end_l as isize), r.offset(-1)); - r = r.offset(-1); + end_l = end_l.sub(1); + ptr::swap(l.add(*end_l as usize), r.sub(1)); + r = r.sub(1); } } width(v.as_mut_ptr(), r) @@ -470,9 +470,9 @@ where while start_r < end_r { // SAFETY: See the reasoning in [remaining-elements-safety]. unsafe { - end_r = end_r.offset(-1); - ptr::swap(l, r.offset(-(*end_r as isize) - 1)); - l = l.offset(1); + end_r = end_r.sub(1); + ptr::swap(l, r.sub((*end_r as usize) + 1)); + l = l.add(1); } } width(v.as_mut_ptr(), l) diff --git a/library/core/src/str/validations.rs b/library/core/src/str/validations.rs index 04bc665233e38..2acef432f2063 100644 --- a/library/core/src/str/validations.rs +++ b/library/core/src/str/validations.rs @@ -216,12 +216,12 @@ pub(super) const fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { // SAFETY: since `align - index` and `ascii_block_size` are // multiples of `usize_bytes`, `block = ptr.add(index)` is // always aligned with a `usize` so it's safe to dereference - // both `block` and `block.offset(1)`. + // both `block` and `block.add(1)`. unsafe { let block = ptr.add(index) as *const usize; // break if there is a nonascii byte let zu = contains_nonascii(*block); - let zv = contains_nonascii(*block.offset(1)); + let zv = contains_nonascii(*block.add(1)); if zu || zv { break; } diff --git a/library/panic_abort/src/android.rs b/library/panic_abort/src/android.rs index 18bb932f10ea9..0fd824f8a458d 100644 --- a/library/panic_abort/src/android.rs +++ b/library/panic_abort/src/android.rs @@ -42,7 +42,7 @@ pub(crate) unsafe fn android_set_abort_message(payload: *mut &mut dyn BoxMeUp) { return; // allocation failure } copy_nonoverlapping(msg.as_ptr(), buf as *mut u8, msg.len()); - buf.offset(msg.len() as isize).write(0); + buf.add(msg.len()).write(0); let func = transmute::(func_addr); func(buf); diff --git a/library/panic_unwind/src/dwarf/eh.rs b/library/panic_unwind/src/dwarf/eh.rs index 7394feab82f22..9aa966b5063b1 100644 --- a/library/panic_unwind/src/dwarf/eh.rs +++ b/library/panic_unwind/src/dwarf/eh.rs @@ -75,7 +75,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result let call_site_encoding = reader.read::(); let call_site_table_length = reader.read_uleb128(); - let action_table = reader.ptr.offset(call_site_table_length as isize); + let action_table = reader.ptr.add(call_site_table_length as usize); let ip = context.ip; if !USING_SJLJ_EXCEPTIONS { diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 9aeae4b2cae69..bb313c7597b6c 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -329,7 +329,7 @@ impl SocketAddr { crate::ptr::copy_nonoverlapping( namespace.as_ptr(), - addr.sun_path.as_mut_ptr().offset(1) as *mut u8, + addr.sun_path.as_mut_ptr().add(1) as *mut u8, namespace.len(), ); let len = (sun_path_offset(&addr) + 1 + namespace.len()) as libc::socklen_t; diff --git a/library/std/src/sys/sgx/abi/usercalls/tests.rs b/library/std/src/sys/sgx/abi/usercalls/tests.rs index cbf7d7d54f7a2..598ad5a083ccd 100644 --- a/library/std/src/sys/sgx/abi/usercalls/tests.rs +++ b/library/std/src/sys/sgx/abi/usercalls/tests.rs @@ -17,12 +17,12 @@ fn test_copy_function() { dst.copy_from_enclave(&[0u8; 100]); // Copy src[0..size] to dst + offset - unsafe { copy_to_userspace(src.as_ptr(), dst.as_mut_ptr().offset(offset), size) }; + unsafe { copy_to_userspace(src.as_ptr(), dst.as_mut_ptr().add(offset), size) }; // Verify copy for byte in 0..size { unsafe { - assert_eq!(*dst.as_ptr().offset(offset + byte as isize), src[byte as usize]); + assert_eq!(*dst.as_ptr().add(offset + byte), src[byte as usize]); } } } diff --git a/library/std/src/sys/windows/alloc.rs b/library/std/src/sys/windows/alloc.rs index fdc81cdea7dec..fe00c08aa6a9a 100644 --- a/library/std/src/sys/windows/alloc.rs +++ b/library/std/src/sys/windows/alloc.rs @@ -168,7 +168,7 @@ unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 { // SAFETY: Because the size and alignment of a header is <= `MIN_ALIGN` and `aligned` // is aligned to at least `MIN_ALIGN` and has at least `MIN_ALIGN` bytes of padding before // it, it is safe to write a header directly before it. - unsafe { ptr::write((aligned as *mut Header).offset(-1), Header(ptr)) }; + unsafe { ptr::write((aligned as *mut Header).sub(1), Header(ptr)) }; // SAFETY: The returned pointer does not point to the to the start of an allocated block, // but there is a header readable directly before it containing the location of the start @@ -213,7 +213,7 @@ unsafe impl GlobalAlloc for System { // SAFETY: Because of the contract of `System`, `ptr` is guaranteed to be non-null // and have a header readable directly before it. - unsafe { ptr::read((ptr as *mut Header).offset(-1)).0 } + unsafe { ptr::read((ptr as *mut Header).sub(1)).0 } } }; diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index aed082b3e0abf..1361b9c90c021 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -512,7 +512,7 @@ impl File { )); } }; - let subst_ptr = path_buffer.offset(subst_off as isize); + let subst_ptr = path_buffer.add(subst_off.into()); let mut subst = slice::from_raw_parts(subst_ptr, subst_len as usize); // Absolute paths start with an NT internal namespace prefix `\??\` // We should not let it leak through. @@ -1345,10 +1345,10 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> { let v = br"\??\"; let v = v.iter().map(|x| *x as u16); for c in v.chain(original.as_os_str().encode_wide()) { - *buf.offset(i) = c; + *buf.add(i) = c; i += 1; } - *buf.offset(i) = 0; + *buf.add(i) = 0; i += 1; (*db).ReparseTag = c::IO_REPARSE_TAG_MOUNT_POINT; (*db).ReparseTargetMaximumLength = (i * 2) as c::WORD; diff --git a/library/std/src/sys/windows/os.rs b/library/std/src/sys/windows/os.rs index bcac996c024ec..352337ba32237 100644 --- a/library/std/src/sys/windows/os.rs +++ b/library/std/src/sys/windows/os.rs @@ -99,11 +99,11 @@ impl Iterator for Env { } let p = self.cur as *const u16; let mut len = 0; - while *p.offset(len) != 0 { + while *p.add(len) != 0 { len += 1; } - let s = slice::from_raw_parts(p, len as usize); - self.cur = self.cur.offset(len + 1); + let s = slice::from_raw_parts(p, len); + self.cur = self.cur.add(len + 1); // Windows allows environment variables to start with an equals // symbol (in any other position, this is the separator between From 3ba393465f262c68e7a2972ea18bc5547cf61340 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 19 Aug 2022 13:33:46 +0400 Subject: [PATCH 20/22] Make some docs nicer wrt pointer offsets --- library/alloc/src/ffi/c_str.rs | 6 +++--- library/alloc/src/vec/mod.rs | 8 ++++---- library/core/src/intrinsics.rs | 2 +- library/core/src/sync/atomic.rs | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index ae61b1f1e8ed5..be21d8c722d78 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -436,9 +436,9 @@ impl CString { /// /// unsafe { /// assert_eq!(b'f', *ptr as u8); - /// assert_eq!(b'o', *ptr.offset(1) as u8); - /// assert_eq!(b'o', *ptr.offset(2) as u8); - /// assert_eq!(b'\0', *ptr.offset(3) as u8); + /// assert_eq!(b'o', *ptr.add(1) as u8); + /// assert_eq!(b'o', *ptr.add(2) as u8); + /// assert_eq!(b'\0', *ptr.add(3) as u8); /// /// // retake pointer to free memory /// let _ = CString::from_raw(ptr); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index fa9f2131c0c1d..fe4dcafe14c32 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -542,8 +542,8 @@ impl Vec { /// /// unsafe { /// // Overwrite memory with 4, 5, 6 - /// for i in 0..len as isize { - /// ptr::write(p.offset(i), 4 + i); + /// for i in 0..len { + /// ptr::write(p.add(i), 4 + i); /// } /// /// // Put everything back together into a Vec @@ -702,8 +702,8 @@ impl Vec { /// /// unsafe { /// // Overwrite memory with 4, 5, 6 - /// for i in 0..len as isize { - /// ptr::write(p.offset(i), 4 + i); + /// for i in 0..len { + /// ptr::write(p.add(i), 4 + i); /// } /// /// // Put everything back together into a Vec diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 15467e0191dbf..3c2a2418aadce 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2211,7 +2211,7 @@ pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) - /// unsafe { /// // The call to offset is always safe because `Vec` will never /// // allocate more than `isize::MAX` bytes. -/// let dst_ptr = dst.as_mut_ptr().offset(dst_len as isize); +/// let dst_ptr = dst.as_mut_ptr().add(dst_len); /// let src_ptr = src.as_ptr(); /// /// // Truncate `src` without dropping its contents. We do this first, diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 40ca9abd6bdc9..21ac9c5c7e3c1 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1555,7 +1555,7 @@ impl AtomicPtr { /// previous pointer. /// /// This is equivalent to using [`wrapping_add`] and [`cast`] to atomically - /// perform `ptr = ptr.cast::().wrapping_add(val).cast::()`. + /// perform `ptr = ptr.wrapping_byte_add(val)`. /// /// `fetch_byte_add` takes an [`Ordering`] argument which describes the /// memory ordering of this operation. All ordering modes are possible. Note @@ -1592,7 +1592,7 @@ impl AtomicPtr { /// previous pointer. /// /// This is equivalent to using [`wrapping_sub`] and [`cast`] to atomically - /// perform `ptr = ptr.cast::().wrapping_sub(val).cast::()`. + /// perform `ptr = ptr.wrapping_byte_sub(val)`. /// /// `fetch_byte_sub` takes an [`Ordering`] argument which describes the /// memory ordering of this operation. All ordering modes are possible. Note From f5be8a4cdaa4c053bce5ae70c4e94246052107a1 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Wed, 17 Aug 2022 07:27:02 -0500 Subject: [PATCH 21/22] Add `rustc --print rustc-path` --- compiler/rustc_driver/src/lib.rs | 4 +++ compiler/rustc_session/src/config.rs | 28 +++++++++++++-------- src/test/run-make/print-rustc-path/Makefile | 9 +++++++ 3 files changed, 30 insertions(+), 11 deletions(-) create mode 100644 src/test/run-make/print-rustc-path/Makefile diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 94639bf8e1ee4..2e678cd54fd87 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -725,6 +725,10 @@ fn print_crate_info( | TargetFeatures => { codegen_backend.print(*req, sess); } + RustcPath => match env::current_exe() { + Ok(exe) => println!("{}", exe.display()), + Err(_) => early_error(ErrorOutputType::default(), "failed to get rustc path"), + }, // Any output here interferes with Cargo's parsing of other printed output NativeStaticLibs => {} LinkArgs => {} diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 68519c8fa828e..3ff6c368e1ef4 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -545,6 +545,7 @@ pub enum PrintRequest { NativeStaticLibs, StackProtectorStrategies, LinkArgs, + RustcPath, } pub enum Input { @@ -1777,6 +1778,20 @@ fn collect_print_requests( cg.target_feature = String::new(); } + let gate = |req, opt| { + if unstable_opts.unstable_options { + req + } else { + early_error( + error_format, + &format!( + "the `-Z unstable-options` flag must also be passed to \ + enable the {opt} print option", + ), + ); + } + }; + prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s { "crate-name" => PrintRequest::CrateName, "file-names" => PrintRequest::FileNames, @@ -1791,18 +1806,9 @@ fn collect_print_requests( "tls-models" => PrintRequest::TlsModels, "native-static-libs" => PrintRequest::NativeStaticLibs, "stack-protector-strategies" => PrintRequest::StackProtectorStrategies, - "target-spec-json" => { - if unstable_opts.unstable_options { - PrintRequest::TargetSpec - } else { - early_error( - error_format, - "the `-Z unstable-options` flag must also be passed to \ - enable the target-spec-json print option", - ); - } - } + "target-spec-json" => gate(PrintRequest::TargetSpec, "target-spec-json"), "link-args" => PrintRequest::LinkArgs, + "rustc-path" => gate(PrintRequest::RustcPath, "rustc-path"), req => early_error(error_format, &format!("unknown print request `{req}`")), })); diff --git a/src/test/run-make/print-rustc-path/Makefile b/src/test/run-make/print-rustc-path/Makefile new file mode 100644 index 0000000000000..b008578082962 --- /dev/null +++ b/src/test/run-make/print-rustc-path/Makefile @@ -0,0 +1,9 @@ +-include ../../run-make-fulldeps/tools.mk + +ifdef IS_WINDOWS +all: + $(RUSTC) -Zunstable-options --print rustc-path | $(CGREP) bin\rustc +else +all: + $(RUSTC) -Zunstable-options --print rustc-path | $(CGREP) bin/rustc +endif From b2625e24b95b5077a1ec59ad6ac667939eb6521f Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sun, 21 Aug 2022 06:36:11 +0400 Subject: [PATCH 22/22] fix nitpicks from review --- library/core/src/intrinsics.rs | 2 +- library/core/src/sync/atomic.rs | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 3c2a2418aadce..3d7b875eac15d 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2209,7 +2209,7 @@ pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) - /// dst.reserve(src_len); /// /// unsafe { -/// // The call to offset is always safe because `Vec` will never +/// // The call to add is always safe because `Vec` will never /// // allocate more than `isize::MAX` bytes. /// let dst_ptr = dst.as_mut_ptr().add(dst_len); /// let src_ptr = src.as_ptr(); diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 21ac9c5c7e3c1..3c96290fc537e 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1554,7 +1554,7 @@ impl AtomicPtr { /// Offsets the pointer's address by adding `val` *bytes*, returning the /// previous pointer. /// - /// This is equivalent to using [`wrapping_add`] and [`cast`] to atomically + /// This is equivalent to using [`wrapping_byte_add`] to atomically /// perform `ptr = ptr.wrapping_byte_add(val)`. /// /// `fetch_byte_add` takes an [`Ordering`] argument which describes the @@ -1565,8 +1565,7 @@ impl AtomicPtr { /// **Note**: This method is only available on platforms that support atomic /// operations on [`AtomicPtr`]. /// - /// [`wrapping_add`]: pointer::wrapping_add - /// [`cast`]: pointer::cast + /// [`wrapping_byte_add`]: pointer::wrapping_byte_add /// /// # Examples /// @@ -1591,7 +1590,7 @@ impl AtomicPtr { /// Offsets the pointer's address by subtracting `val` *bytes*, returning the /// previous pointer. /// - /// This is equivalent to using [`wrapping_sub`] and [`cast`] to atomically + /// This is equivalent to using [`wrapping_byte_sub`] to atomically /// perform `ptr = ptr.wrapping_byte_sub(val)`. /// /// `fetch_byte_sub` takes an [`Ordering`] argument which describes the @@ -1602,8 +1601,7 @@ impl AtomicPtr { /// **Note**: This method is only available on platforms that support atomic /// operations on [`AtomicPtr`]. /// - /// [`wrapping_sub`]: pointer::wrapping_sub - /// [`cast`]: pointer::cast + /// [`wrapping_byte_sub`]: pointer::wrapping_byte_sub /// /// # Examples ///