diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 3270fb940bab3..fb33f2823372b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1180,7 +1180,7 @@ impl<'a> AstValidator<'a> { self.dcx().emit_err(diagnostics::ArgsBeforeConstraint { arg_spans: arg_spans.clone(), constraints: constraint_spans[0], - args: *arg_spans.iter().last().unwrap(), + args: *arg_spans.last().unwrap(), data: data.span, constraint_spans: diagnostics::EmptyLabelManySpans(constraint_spans), arg_spans2: diagnostics::EmptyLabelManySpans(arg_spans), diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index bd92f32e24b68..25bacacd85036 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -505,7 +505,8 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!( closure_lifetime_binder, "`for<...>` binders for closures are experimental", - "consider removing `for<...>`" + "consider using a type annotation instead: \ + `let closure: for<...> fn(...) -> ... = /* closure */;`" ); gate_all!( half_open_range_patterns_in_slices, diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 7a2670f3b1b78..7f38aeb5ac3fa 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -324,7 +324,7 @@ fn extend_err_with_const_context( { // `foo()`, point at the const parameter in the definition of `foo`. if let Some(i) = - path.segments.iter().last().and_then(|segment| segment.args).and_then(|args| { + path.segments.last().and_then(|segment| segment.args).and_then(|args| { args.args.iter().position(|arg| { matches!(arg, hir::GenericArg::Const(arg) if arg.hir_id == parent.hir_id) }) diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index d017a27e8f77f..266a2d134199c 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1688,7 +1688,7 @@ impl<'a> Parser<'a> { /// If the user writes `S { ref field: name }` instead of `S { field: ref name }`, we suggest /// the correct code. fn recover_misplaced_pattern_modifiers(&self, fields: &ThinVec, err: &mut Diag<'a>) { - if let Some(last) = fields.iter().last() + if let Some(last) = fields.last() && last.is_shorthand && let PatKind::Ident(binding, ident, None) = last.pat.kind && binding != BindingMode::NONE diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 9fa762c87ef3e..149f34cb6c35d 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -256,9 +256,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { for note in notes { diag.note(note); } - } else if let Some((_, UnresolvedImportError { note: Some(note), .. })) = - errors.iter().last() - { + } else if let Some((_, UnresolvedImportError { note: Some(note), .. })) = errors.last() { diag.note(note.clone()); } @@ -2876,7 +2874,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if struct_expr.fields.is_empty() { return; } - let last_span = struct_expr.fields.iter().last().unwrap().span; + let last_span = struct_expr.fields.last().unwrap().span; let mut iter = struct_expr.fields.iter().peekable(); let mut prev: Option = None; while let Some(field) = iter.next() { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index c21d3653a13be..543082a6af7fc 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4092,7 +4092,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { v.could_be_path = false; } self.report_error( - v.origin.iter().next().unwrap().0, + v.origin.first().unwrap().0, ResolutionError::VariableNotBoundInPattern(v, self.parent_scope), ); } @@ -4757,8 +4757,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_path(&std_path, Some(ns), None, source) { // Check if we wrote `str::from_utf8` instead of `std::str::from_utf8` - let item_span = - path.iter().last().map_or(path_span, |segment| segment.ident.span); + let item_span = path.last().map_or(path_span, |segment| segment.ident.span); self.r.confused_type_with_std_module.insert(item_span, path_span); self.r.confused_type_with_std_module.insert(path_span, path_span); diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index d1c7cd47da0f0..b6a7a1eae2a70 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -188,7 +188,7 @@ impl<'a, B: ?Sized + ToOwned> Borrow for Cow<'a, B> // B::Owned: [const] Borrow, { fn borrow(&self) -> &B { - &**self + self } } diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index bf91ac9dc3e74..ea19769e17682 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2144,7 +2144,7 @@ impl Clone for Box<[T], A> { /// ``` fn clone_from(&mut self, source: &Self) { if self.len() == source.len() { - self.clone_from_slice(&source); + self.clone_from_slice(source); } else { *self = source.clone(); } @@ -2295,14 +2295,14 @@ impl Deref for Box { type Target = T; fn deref(&self) -> &T { - &**self + self } } #[stable(feature = "rust1", since = "1.0.0")] impl DerefMut for Box { fn deref_mut(&mut self) -> &mut T { - &mut **self + self } } @@ -2398,28 +2398,28 @@ impl, U: ?Sized> DispatchFromDyn> for Box Borrow for Box { fn borrow(&self) -> &T { - &**self + self } } #[stable(feature = "box_borrow", since = "1.1.0")] impl BorrowMut for Box { fn borrow_mut(&mut self) -> &mut T { - &mut **self + self } } #[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] impl AsRef for Box { fn as_ref(&self) -> &T { - &**self + self } } #[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] impl AsMut for Box { fn as_mut(&mut self) -> &mut T { - &mut **self + self } } diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 0a1f7738632c1..d8421d3c3f70a 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -1572,7 +1572,7 @@ impl BTreeMap { let right_root = left_root.split_off(key, (*self.alloc).clone()); - let (new_left_len, right_len) = Root::calc_split_length(total_num, &left_root, &right_root); + let (new_left_len, right_len) = Root::calc_split_length(total_num, left_root, &right_root); self.length = new_left_len; BTreeMap { @@ -2208,8 +2208,8 @@ impl<'a, K, V, R> ExtractIfInner<'a, K, V, R> { // On creation, we navigated directly to the left bound, so we need only check the // right bound here to decide whether to stop. match self.range.end_bound() { - Bound::Included(ref end) if (*k).le(end) => (), - Bound::Excluded(ref end) if (*k).lt(end) => (), + Bound::Included(end) if (*k).le(end) => (), + Bound::Excluded(end) if (*k).lt(end) => (), Bound::Unbounded => (), _ => return None, } diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 84dd4b7e49def..0c7afcc63b9b7 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -1430,7 +1430,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { left_node.val_area_mut(old_left_len + 1..new_left_len), ); - slice_remove(&mut parent_node.edge_area_mut(..old_parent_len + 1), parent_idx + 1); + slice_remove(parent_node.edge_area_mut(..old_parent_len + 1), parent_idx + 1); parent_node.correct_childrens_parent_links(parent_idx + 1..old_parent_len); *parent_node.len_mut() -= 1; diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 2a483b3d3982e..d06daa7c6c1b7 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1971,7 +1971,7 @@ impl<'a, T: Ord, A: Allocator + Clone> Iterator for Difference<'a, T, A> { } DifferenceInner::Search { self_iter, other_set } => loop { let self_next = self_iter.next()?; - if !other_set.contains(&self_next) { + if !other_set.contains(self_next) { return Some(self_next); } }, @@ -2068,7 +2068,7 @@ impl<'a, T: Ord, A: Allocator + Clone> Iterator for Intersection<'a, T, A> { } IntersectionInner::Search { small_iter, large_set } => loop { let small_next = small_iter.next()?; - if large_set.contains(&small_next) { + if large_set.contains(small_next) { return Some(small_next); } }, diff --git a/library/alloc/src/io/impls.rs b/library/alloc/src/io/impls.rs index a6c9428ba62dc..0296cada74171 100644 --- a/library/alloc/src/io/impls.rs +++ b/library/alloc/src/io/impls.rs @@ -327,7 +327,7 @@ impl Read for &[u8] { fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_, u8>) -> io::Result<()> { if cursor.capacity() > self.len() { // Append everything we can to the cursor. - cursor.append(*self); + cursor.append(self); *self = &self[self.len()..]; return Err(io::Error::READ_EXACT_EOF); } @@ -349,7 +349,7 @@ impl Read for &[u8] { buf.try_extend_from_slice_of_bytes(*self)?; } _ => { - buf.extend_from_slice(*self); + buf.extend_from_slice(self); } } @@ -625,7 +625,7 @@ where #[inline] fn is_read_vectored(&self) -> bool { - (&**self).is_read_vectored() + (**self).is_read_vectored() } #[inline] @@ -667,7 +667,7 @@ where #[inline] fn is_write_vectored(&self) -> bool { - (&**self).is_write_vectored() + (**self).is_write_vectored() } #[inline] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index e639a32370703..8af62ffc39237 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -3858,14 +3858,14 @@ impl<'a> RcInnerPtr for WeakInner<'a> { #[stable(feature = "rust1", since = "1.0.0")] impl borrow::Borrow for Rc { fn borrow(&self) -> &T { - &**self + self } } #[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] impl AsRef for Rc { fn as_ref(&self) -> &T { - &**self + self } } @@ -3990,28 +3990,28 @@ impl fmt::Pointer for UniqueRc { #[unstable(feature = "unique_rc_arc", issue = "112566")] impl borrow::Borrow for UniqueRc { fn borrow(&self) -> &T { - &**self + self } } #[unstable(feature = "unique_rc_arc", issue = "112566")] impl borrow::BorrowMut for UniqueRc { fn borrow_mut(&mut self) -> &mut T { - &mut **self + self } } #[unstable(feature = "unique_rc_arc", issue = "112566")] impl AsRef for UniqueRc { fn as_ref(&self) -> &T { - &**self + self } } #[unstable(feature = "unique_rc_arc", issue = "112566")] impl AsMut for UniqueRc { fn as_mut(&mut self) -> &mut T { - &mut **self + self } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 5ea0fd3a394d4..af0211af0dc25 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3836,7 +3836,7 @@ impl Default for Arc { #[inline] fn default() -> Self { let arc: Arc<[u8]> = Default::default(); - debug_assert!(core::str::from_utf8(&*arc).is_ok()); + debug_assert!(core::str::from_utf8(&arc).is_ok()); let (ptr, alloc) = Arc::into_inner_with_allocator(arc); unsafe { Arc::from_ptr_in(ptr.as_ptr() as *mut ArcInner, alloc) } } @@ -4246,14 +4246,14 @@ impl> ToArcSlice for I { #[stable(feature = "rust1", since = "1.0.0")] impl borrow::Borrow for Arc { fn borrow(&self) -> &T { - &**self + self } } #[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] impl AsRef for Arc { fn as_ref(&self) -> &T { - &**self + self } } @@ -4463,28 +4463,28 @@ impl fmt::Pointer for UniqueArc { #[unstable(feature = "unique_rc_arc", issue = "112566")] impl borrow::Borrow for UniqueArc { fn borrow(&self) -> &T { - &**self + self } } #[unstable(feature = "unique_rc_arc", issue = "112566")] impl borrow::BorrowMut for UniqueArc { fn borrow_mut(&mut self) -> &mut T { - &mut **self + self } } #[unstable(feature = "unique_rc_arc", issue = "112566")] impl AsRef for UniqueArc { fn as_ref(&self) -> &T { - &**self + self } } #[unstable(feature = "unique_rc_arc", issue = "112566")] impl AsMut for UniqueArc { fn as_mut(&mut self) -> &mut T { - &mut **self + self } } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 897b8af0eeed1..bc62e4336f8cf 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3878,7 +3878,7 @@ impl Clone for Vec { /// capacity of the original. fn clone(&self) -> Self { let alloc = self.allocator().clone(); - <[T]>::to_vec_in(&**self, alloc) + <[T]>::to_vec_in(self, alloc) } /// Overwrites the contents of `self` with a clone of the contents of `source`. diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs index 99ebcb4ada296..6436afd1ba12f 100644 --- a/library/alloc/src/vec/splice.rs +++ b/library/alloc/src/vec/splice.rs @@ -59,7 +59,7 @@ impl Drop for Splice<'_, I, A> { // Which means we can replace the slice::Iter with pointers that won't point to deallocated // memory, so that Drain::drop is still allowed to call iter.len(), otherwise it would break // the ptr.offset_from_unsigned contract. - self.drain.iter = (&[]).iter(); + self.drain.iter = [].iter(); unsafe { if self.drain.tail_len == 0 { diff --git a/library/alloc/src/wtf8/mod.rs b/library/alloc/src/wtf8/mod.rs index 394c41bf36727..36ec32c549763 100644 --- a/library/alloc/src/wtf8/mod.rs +++ b/library/alloc/src/wtf8/mod.rs @@ -284,7 +284,7 @@ impl Wtf8Buf { /// like concatenating ill-formed UTF-16 strings effectively would. #[inline] pub fn push_wtf8(&mut self, other: &Wtf8) { - match ((&*self).final_lead_surrogate(), other.initial_trail_surrogate()) { + match ((*self).final_lead_surrogate(), other.initial_trail_surrogate()) { // Replace newly paired surrogates by a supplementary code point. (Some(lead), Some(trail)) => { let len_without_lead_surrogate = self.len() - 3; @@ -322,7 +322,7 @@ impl Wtf8Buf { #[inline] pub fn push(&mut self, code_point: CodePoint) { if let Some(trail) = code_point.to_trail_surrogate() { - if let Some(lead) = (&*self).final_lead_surrogate() { + if let Some(lead) = (*self).final_lead_surrogate() { let len_without_lead_surrogate = self.len() - 3; self.bytes.truncate(len_without_lead_surrogate); self.push_char(decode_surrogate_pair(lead, trail)); diff --git a/library/core/src/bstr/traits.rs b/library/core/src/bstr/traits.rs index bcfffd52d7419..1d8d0e29e9a5a 100644 --- a/library/core/src/bstr/traits.rs +++ b/library/core/src/bstr/traits.rs @@ -25,7 +25,7 @@ impl PartialOrd for ByteStr { impl PartialEq for ByteStr { #[inline] fn eq(&self, other: &ByteStr) -> bool { - &self.0 == &other.0 + self.0 == other.0 } } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 2dc2c5981cafd..e8cd3a500084a 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -704,7 +704,7 @@ impl AsRef<[Cell; N]> for Cell<[T; N]> { impl AsRef<[Cell]> for Cell<[T; N]> { #[inline] fn as_ref(&self) -> &[Cell] { - &*self.as_array_of_cells() + self.as_array_of_cells() } } diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 2996c753faea4..f124b8bceaded 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -781,7 +781,7 @@ mod impls { #[inline(always)] #[rustc_diagnostic_item = "noop_method_clone"] fn clone(&self) -> Self { - *self + self } } diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 10fab83eda348..e5b1f8088a5bf 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -687,7 +687,7 @@ impl PartialEq<&Self> for CStr { impl PartialOrd for CStr { #[inline] fn partial_cmp(&self, other: &CStr) -> Option { - self.to_bytes().partial_cmp(&other.to_bytes()) + self.to_bytes().partial_cmp(other.to_bytes()) } } @@ -695,7 +695,7 @@ impl PartialOrd for CStr { impl Ord for CStr { #[inline] fn cmp(&self, other: &CStr) -> Ordering { - self.to_bytes().cmp(&other.to_bytes()) + self.to_bytes().cmp(other.to_bytes()) } } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 47886aa7165d9..6a4c58afc16f3 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -3189,7 +3189,7 @@ impl Debug for Ref<'_, T> { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for RefMut<'_, T> { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - Debug::fmt(&*(self.deref()), f) + Debug::fmt(self.deref(), f) } } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 28b5bba6be207..120c6de3c621d 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4080,7 +4080,7 @@ pub const trait Iterator { mut compare: impl FnMut(&T, &T) -> bool + 'a, ) -> impl FnMut(T) -> bool + 'a { move |curr| { - if !compare(&last, &curr) { + if !compare(last, &curr) { return false; } *last = curr; diff --git a/library/core/src/mem/drop_guard.rs b/library/core/src/mem/drop_guard.rs index 70658f0efb242..8e6655f785466 100644 --- a/library/core/src/mem/drop_guard.rs +++ b/library/core/src/mem/drop_guard.rs @@ -116,7 +116,7 @@ where type Target = T; fn deref(&self) -> &T { - &*self.inner + &self.inner } } @@ -127,7 +127,7 @@ where F: FnOnce(T), { fn deref_mut(&mut self) -> &mut T { - &mut *self.inner + &mut self.inner } } diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 6275d7cd59a2c..94703940baa1f 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -1639,7 +1639,7 @@ impl AsRef<[MaybeUninit; N]> for MaybeUninit<[T; N]> { impl AsRef<[MaybeUninit]> for MaybeUninit<[T; N]> { #[inline] fn as_ref(&self) -> &[MaybeUninit] { - &*AsRef::<[MaybeUninit; N]>::as_ref(self) + AsRef::<[MaybeUninit; N]>::as_ref(self) } } diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 52a84082f3b92..58e63ff04af15 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1540,7 +1540,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { U: ?Sized, F: FnOnce(&T) -> &U, { - let pointer = &*self.pointer; + let pointer = self.pointer; let new_pointer = func(pointer); // SAFETY: the safety contract for `new_unchecked` must be diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index bc99290a38dfc..2b6037b2ee53e 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -91,7 +91,7 @@ impl [u8] { let mut b = other; while let ([first_a, rest_a @ ..], [first_b, rest_b @ ..]) = (a, b) { - if first_a.eq_ignore_ascii_case(&first_b) { + if first_a.eq_ignore_ascii_case(first_b) { a = rest_a; b = rest_b; } else { diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 6f75808015e71..a054c9d742c88 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -424,7 +424,7 @@ impl<'a, T: 'a, P: FnMut(&T) -> bool> Split<'a, T, P> { /// ``` #[unstable(feature = "split_as_slice", issue = "96137")] pub fn as_slice(&self) -> &'a [T] { - if self.finished { &[] } else { &self.v } + if self.finished { &[] } else { self.v } } } diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 70d9c7aef2a74..26c48d48d211e 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -1410,7 +1410,7 @@ impl<'a> SplitAsciiWhitespace<'a> { } // SAFETY: Slice is created from str. - Some(unsafe { crate::str::from_utf8_unchecked(&self.inner.iter.iter.v) }) + Some(unsafe { crate::str::from_utf8_unchecked(self.inner.iter.iter.v) }) } } diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index 38006b638fdcd..e157ab588e701 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -1051,7 +1051,7 @@ impl<'b> Pattern for &'b str { #[inline] fn as_utf8_pattern(&self) -> Option> { - Some(Utf8Pattern::StringPattern(*self)) + Some(Utf8Pattern::StringPattern(self)) } } diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 63b7691582a7d..473b185d24652 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -245,14 +245,14 @@ impl<'a> Context<'a> { #[stable(feature = "futures_api", since = "1.36.0")] #[rustc_const_stable(feature = "const_waker", since = "1.82.0")] pub const fn waker(&self) -> &'a Waker { - &self.waker + self.waker } /// Returns a reference to the [`LocalWaker`] for the current task. #[inline] #[unstable(feature = "local_waker", issue = "118959")] pub const fn local_waker(&self) -> &'a LocalWaker { - &self.local_waker + self.local_waker } /// Returns a reference to the extension data for the current task. diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 73fb3f54097fa..27039f0d3d2eb 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -719,7 +719,7 @@ impl fmt::Debug for OsString { impl PartialEq for OsString { #[inline] fn eq(&self, other: &OsString) -> bool { - &**self == &**other + **self == **other } } @@ -762,23 +762,23 @@ impl Eq for OsString {} impl PartialOrd for OsString { #[inline] fn partial_cmp(&self, other: &OsString) -> Option { - (&**self).partial_cmp(&**other) + (**self).partial_cmp(&**other) } #[inline] fn lt(&self, other: &OsString) -> bool { - &**self < &**other + **self < **other } #[inline] fn le(&self, other: &OsString) -> bool { - &**self <= &**other + **self <= **other } #[inline] fn gt(&self, other: &OsString) -> bool { - &**self > &**other + **self > **other } #[inline] fn ge(&self, other: &OsString) -> bool { - &**self >= &**other + **self >= **other } } @@ -786,7 +786,7 @@ impl PartialOrd for OsString { impl PartialOrd for OsString { #[inline] fn partial_cmp(&self, other: &str) -> Option { - (&**self).partial_cmp(other) + (**self).partial_cmp(other) } } @@ -794,7 +794,7 @@ impl PartialOrd for OsString { impl Ord for OsString { #[inline] fn cmp(&self, other: &OsString) -> cmp::Ordering { - (&**self).cmp(&**other) + (**self).cmp(&**other) } } @@ -802,7 +802,7 @@ impl Ord for OsString { impl Hash for OsString { #[inline] fn hash(&self, state: &mut H) { - (&**self).hash(state) + (**self).hash(state) } } @@ -1777,7 +1777,7 @@ impl AsRef for str { impl AsRef for String { #[inline] fn as_ref(&self) -> &OsStr { - (&**self).as_ref() + (**self).as_ref() } } diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 58874a27f8ae5..61e62e2064952 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1497,7 +1497,7 @@ impl Read for File { } #[inline] fn is_read_vectored(&self) -> bool { - (&&*self).is_read_vectored() + (&self).is_read_vectored() } fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { (&*self).read_to_end(buf) @@ -1516,7 +1516,7 @@ impl Write for File { } #[inline] fn is_write_vectored(&self) -> bool { - (&&*self).is_write_vectored() + (&self).is_write_vectored() } #[inline] fn flush(&mut self) -> io::Result<()> { diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 957235f9f3fb0..b104ea69cd1fc 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -796,7 +796,7 @@ impl Write for Stdout { } #[inline] fn is_write_vectored(&self) -> bool { - io::Write::is_write_vectored(&&*self) + io::Write::is_write_vectored(&self) } fn flush(&mut self) -> io::Result<()> { (&*self).flush() @@ -1028,7 +1028,7 @@ impl Write for Stderr { } #[inline] fn is_write_vectored(&self) -> bool { - io::Write::is_write_vectored(&&*self) + io::Write::is_write_vectored(&self) } fn flush(&mut self) -> io::Result<()> { (&*self).flush() diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 22ac7443f464b..d3bbb7c2353cd 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -740,7 +740,7 @@ mod panicking; #[path = "../../backtrace/src/lib.rs"] #[allow(dead_code, unused_attributes, implicit_provenance_casts, unsafe_op_in_unsafe_fn)] -#[allow(clippy::len_zero)] // FIXME +#[allow(clippy::len_zero, clippy::needless_borrow)] // FIXME mod backtrace_rs; #[stable(feature = "cfg_select", since = "1.95.0")] diff --git a/library/std/src/net/socket_addr.rs b/library/std/src/net/socket_addr.rs index 2dab8c26f1f6b..6aa625d66a363 100644 --- a/library/std/src/net/socket_addr.rs +++ b/library/std/src/net/socket_addr.rs @@ -257,6 +257,6 @@ impl ToSocketAddrs for &T { impl ToSocketAddrs for String { type Iter = vec::IntoIter; fn to_socket_addrs(&self) -> io::Result> { - (&**self).to_socket_addrs() + (**self).to_socket_addrs() } } diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 08cd6138591e4..3daddc2d34323 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -262,12 +262,10 @@ impl SocketAddr { } else if self.addr.sun_path[0] == 0 { AddressKind::Abstract(ByteStr::from_bytes(&path[1..len])) } else { - // the value returned by getsockname(2) and similar on QNX7.1 and - // QNX8 does not count the NUL byte terminator of the path string, - // which matches the behavior of the SUN_LEN macro in libc, but - // other OSes do count the NUL byte so adjust accordingly - let end = - if cfg!(any(target_os = "qnx", target_env = "nto71")) { len } else { len - 1 }; + // linux adds a trailing NUL and counts it in the length, freebsd, netbsd + // and qnx do not, and a caller may bind(2) without one either. unix(7) + // gives the portable rule: strnlen(sun_path, len - offsetof(sun_path)) + let end = core::slice::memchr::memchr(0, &path[..len]).unwrap_or(len); AddressKind::Pathname(OsStr::from_bytes(&path[..end]).as_ref()) } } diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index a9029f7fa0bfb..bdf0384e34f80 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -506,12 +506,12 @@ impl<'a> AncillaryData<'a> { fn try_from_cmsghdr(cmsg: &'a libc::cmsghdr) -> Result { unsafe { let cmsg_len_zero = libc::CMSG_LEN(0) as usize; - let data_len = (*cmsg).cmsg_len as usize - cmsg_len_zero; + let data_len = cmsg.cmsg_len as usize - cmsg_len_zero; let data = libc::CMSG_DATA(cmsg).cast(); let data = from_raw_parts(data, data_len); - match (*cmsg).cmsg_level { - libc::SOL_SOCKET => match (*cmsg).cmsg_type { + match cmsg.cmsg_level { + libc::SOL_SOCKET => match cmsg.cmsg_type { libc::SCM_RIGHTS => Ok(AncillaryData::as_rights(data)), #[cfg(any(target_os = "android", target_os = "linux", target_os = "cygwin"))] libc::SCM_CREDENTIALS => Ok(AncillaryData::as_credentials(data)), @@ -524,7 +524,7 @@ impl<'a> AncillaryData<'a> { } }, cmsg_level => { - Err(AncillaryError::Unknown { cmsg_level, cmsg_type: (*cmsg).cmsg_type }) + Err(AncillaryError::Unknown { cmsg_level, cmsg_type: cmsg.cmsg_type }) } } } @@ -744,7 +744,7 @@ impl<'a> SocketAncillary<'a> { pub fn add_fds(&mut self, fds: &[RawFd]) -> bool { self.truncated = false; add_to_ancillary_data( - &mut self.buffer, + self.buffer, &mut self.length, fds, libc::SOL_SOCKET, @@ -771,7 +771,7 @@ impl<'a> SocketAncillary<'a> { pub fn add_creds(&mut self, creds: &[SocketCred]) -> bool { self.truncated = false; add_to_ancillary_data( - &mut self.buffer, + self.buffer, &mut self.length, creds, libc::SOL_SOCKET, diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 8567e2fbb783d..9a17f9e0b8b9b 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -642,7 +642,7 @@ impl io::Read for UnixStream { #[inline] fn is_read_vectored(&self) -> bool { - io::Read::is_read_vectored(&&*self) + io::Read::is_read_vectored(&self) } } @@ -678,7 +678,7 @@ impl io::Write for UnixStream { #[inline] fn is_write_vectored(&self) -> bool { - io::Write::is_write_vectored(&&*self) + io::Write::is_write_vectored(&self) } fn flush(&mut self) -> io::Result<()> { diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs index 3ba4b44d2f1ef..9c3119e787b33 100644 --- a/library/std/src/os/unix/net/tests.rs +++ b/library/std/src/os/unix/net/tests.rs @@ -29,6 +29,29 @@ fn sock_addr_from_pathname() { assert_eq!(address.as_pathname(), Some(Path::new("/path/to/socket"))); } +// the trailing NUL is not counted in the reported length on freebsd, netbsd +// and qnx, and a caller may bind(2) without one anywhere +#[test] +fn sock_addr_without_trailing_nul() { + const PATH: &[u8] = b"/path/to/socket"; + + // SAFETY: all zeros is a valid representation for `sockaddr_un`. + let mut addr: libc::sockaddr_un = unsafe { crate::mem::zeroed() }; + addr.sun_family = libc::AF_UNIX as libc::sa_family_t; + for (dst, &src) in addr.sun_path.iter_mut().zip(PATH) { + *dst = src as _; + } + let offset = crate::mem::offset_of!(libc::sockaddr_un, sun_path); + + // length excluding the NUL, as reported by freebsd, netbsd and qnx + let address = or_panic!(SocketAddr::from_parts(addr, (offset + PATH.len()) as _)); + assert_eq!(address.as_pathname(), Some(Path::new("/path/to/socket"))); + + // length including the NUL, as reported by linux + let address = or_panic!(SocketAddr::from_parts(addr, (offset + PATH.len() + 1) as _)); + assert_eq!(address.as_pathname(), Some(Path::new("/path/to/socket"))); +} + #[test] #[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets #[cfg_attr(target_os = "vxworks", ignore = "Unix sockets are not implemented in VxWorks")] diff --git a/library/std/src/path.rs b/library/std/src/path.rs index be216d87f3241..8b41a3792ac9a 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2673,7 +2673,7 @@ impl Path { #[stable(feature = "path_ancestors", since = "1.28.0")] #[inline] pub fn ancestors(&self) -> Ancestors<'_> { - Ancestors { next: Some(&self) } + Ancestors { next: Some(self) } } /// Returns the final component of the `Path`, if there is one. diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 9f0bf72f755f4..a4c461737b620 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -333,7 +333,7 @@ impl Write for ChildStdin { } fn is_write_vectored(&self) -> bool { - io::Write::is_write_vectored(&&*self) + io::Write::is_write_vectored(&self) } #[inline] diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index 9bb25287275b2..f150d42a3137c 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -258,7 +258,7 @@ impl T> LazyLock { // * the closure was not called, but a previous call initialized `value`. // * the closure was not called because the Once is poisoned, which we handled above. // So `value` has definitely been initialized and will not be modified again. - unsafe { &*(*this.data.get()).value } + unsafe { &(*this.data.get()).value } } } diff --git a/library/std/src/sync/nonpoison/rwlock.rs b/library/std/src/sync/nonpoison/rwlock.rs index dc5d9479ba5a9..19064fdd1ce10 100644 --- a/library/std/src/sync/nonpoison/rwlock.rs +++ b/library/std/src/sync/nonpoison/rwlock.rs @@ -636,7 +636,7 @@ impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> { // reference passed to it. If the closure panics, the guard will be dropped. let data = NonNull::from(f(unsafe { orig.data.as_ref() })); let orig = ManuallyDrop::new(orig); - MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock } + MappedRwLockReadGuard { data, inner_lock: orig.inner_lock } } /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data. The @@ -668,7 +668,7 @@ impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> { Some(data) => { let data = NonNull::from(data); let orig = ManuallyDrop::new(orig); - Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }) + Ok(MappedRwLockReadGuard { data, inner_lock: orig.inner_lock }) } None => Err(orig), } @@ -861,7 +861,7 @@ impl<'rwlock, T: ?Sized> MappedRwLockReadGuard<'rwlock, T> { // reference passed to it. If the closure panics, the guard will be dropped. let data = NonNull::from(f(unsafe { orig.data.as_ref() })); let orig = ManuallyDrop::new(orig); - MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock } + MappedRwLockReadGuard { data, inner_lock: orig.inner_lock } } /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data. @@ -893,7 +893,7 @@ impl<'rwlock, T: ?Sized> MappedRwLockReadGuard<'rwlock, T> { Some(data) => { let data = NonNull::from(data); let orig = ManuallyDrop::new(orig); - Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }) + Ok(MappedRwLockReadGuard { data, inner_lock: orig.inner_lock }) } None => Err(orig), } diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index 4cfd9d19df74a..de1fedf88f63a 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -770,7 +770,7 @@ impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> { // reference passed to it. If the closure panics, the guard will be dropped. let data = NonNull::from(f(unsafe { orig.data.as_ref() })); let orig = ManuallyDrop::new(orig); - MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock } + MappedRwLockReadGuard { data, inner_lock: orig.inner_lock } } /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data. The @@ -802,7 +802,7 @@ impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> { Some(data) => { let data = NonNull::from(data); let orig = ManuallyDrop::new(orig); - Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }) + Ok(MappedRwLockReadGuard { data, inner_lock: orig.inner_lock }) } None => Err(orig), } @@ -996,7 +996,7 @@ impl<'rwlock, T: ?Sized> MappedRwLockReadGuard<'rwlock, T> { // reference passed to it. If the closure panics, the guard will be dropped. let data = NonNull::from(f(unsafe { orig.data.as_ref() })); let orig = ManuallyDrop::new(orig); - MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock } + MappedRwLockReadGuard { data, inner_lock: orig.inner_lock } } /// Makes a [`MappedRwLockReadGuard`] for a component of the borrowed data. @@ -1028,7 +1028,7 @@ impl<'rwlock, T: ?Sized> MappedRwLockReadGuard<'rwlock, T> { Some(data) => { let data = NonNull::from(data); let orig = ManuallyDrop::new(orig); - Ok(MappedRwLockReadGuard { data, inner_lock: &orig.inner_lock }) + Ok(MappedRwLockReadGuard { data, inner_lock: orig.inner_lock }) } None => Err(orig), } diff --git a/library/std/src/sys/fs/common.rs b/library/std/src/sys/fs/common.rs index 68aed39d1dcdf..edc31d21ca1fa 100644 --- a/library/std/src/sys/fs/common.rs +++ b/library/std/src/sys/fs/common.rs @@ -72,7 +72,7 @@ impl Dir { } pub fn open_file(&self, path: &Path, opts: &OpenOptions) -> io::Result { - File::open(&self.path.join(path), &opts) + File::open(&self.path.join(path), opts) } pub fn metadata(&self) -> io::Result { diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 885e56ed2c6b1..2b7e4b9ba6860 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -2415,7 +2415,7 @@ mod remove_dir_impl { fn remove_dir_all_recursive(parent_fd: Option, path: &CStr) -> io::Result<()> { // try opening as directory - let fd = match openat_nofollow_dironly(parent_fd, &path) { + let fd = match openat_nofollow_dironly(parent_fd, path) { Err(err) if matches!(err.raw_os_error(), Some(libc::ENOTDIR | libc::ELOOP)) => { // not a directory - don't traverse further // (for symlinks, older Linux kernels may return ELOOP instead of ENOTDIR) @@ -2485,7 +2485,7 @@ mod remove_dir_impl { if attr.file_type().is_symlink() { super::unlink(p) } else { - remove_dir_all_recursive(None, &p) + remove_dir_all_recursive(None, p) } } diff --git a/library/std/src/sys/fs/unix/dir.rs b/library/std/src/sys/fs/unix/dir.rs index f3f612a225ed1..13a17350ff7b9 100644 --- a/library/std/src/sys/fs/unix/dir.rs +++ b/library/std/src/sys/fs/unix/dir.rs @@ -38,7 +38,7 @@ impl Dir { } pub fn open_file(&self, path: &Path, opts: &OpenOptions) -> io::Result { - run_path_with_cstr(path.as_ref(), &|path| self.open_file_c(path, &opts)) + run_path_with_cstr(path.as_ref(), &|path| self.open_file_c(path, opts)) } pub fn metadata(&self) -> io::Result { diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index c1d21d07d9952..c10b266ccb726 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -339,7 +339,7 @@ impl File { let path = maybe_verbatim(path)?; // SAFETY: maybe_verbatim returns null-terminated strings let path = unsafe { WCStr::from_wchars_with_null_unchecked(&path) }; - Self::open_native(&path, opts) + Self::open_native(path, opts) } fn open_native(path: &WCStr, opts: &OpenOptions) -> io::Result { @@ -1305,7 +1305,7 @@ pub fn unlink(path: &WCStr) -> io::Result<()> { let mut opts = OpenOptions::new(); opts.access_mode(c::DELETE); opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT); - if let Ok(f) = File::open_native(&path, &opts) { + if let Ok(f) = File::open_native(path, &opts) { if f.posix_delete().is_ok() { return Ok(()); } @@ -1328,7 +1328,7 @@ pub fn rename(old: &WCStr, new: &WCStr) -> io::Result<()> { let mut opts = OpenOptions::new(); opts.access_mode(c::DELETE); opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS); - let Ok(f) = File::open_native(&old, &opts) else { return Err(err).io_result() }; + let Ok(f) = File::open_native(old, &opts) else { return Err(err).io_result() }; // Calculate the layout of the `FILE_RENAME_INFO` we pass to `SetFileInformation` // This is a dynamically sized struct so we need to get the position of the last field to calculate the actual size. @@ -1419,7 +1419,7 @@ pub fn readlink(path: &WCStr) -> io::Result { let mut opts = OpenOptions::new(); opts.access_mode(0); opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS); - let file = File::open_native(&path, &opts)?; + let file = File::open_native(path, &opts)?; file.readlink() } @@ -1506,7 +1506,7 @@ fn metadata(path: &WCStr, reparse: ReparsePoint) -> io::Result { // Attempt to open the file normally. // If that fails with `ERROR_SHARING_VIOLATION` then retry using `FindFirstFileExW`. // If the fallback fails for any reason we return the original error. - match File::open_native(&path, &opts) { + match File::open_native(path, &opts) { Ok(file) => file.file_attr(), Err(e) if [Some(c::ERROR_SHARING_VIOLATION as _), Some(c::ERROR_ACCESS_DENIED as _)] diff --git a/library/std/src/sys/path/windows.rs b/library/std/src/sys/path/windows.rs index 1c7bf50d1907f..2dbe33e2cf8b0 100644 --- a/library/std/src/sys/path/windows.rs +++ b/library/std/src/sys/path/windows.rs @@ -251,6 +251,6 @@ pub(crate) fn is_absolute_exact(path: &[u16]) -> bool { unsafe { new_path.set_len((result as usize) + 1); } - path == &new_path + path == new_path } } diff --git a/library/std/src/sys/process/unix/common.rs b/library/std/src/sys/process/unix/common.rs index 2e32770e90e77..a67c14b58faf1 100644 --- a/library/std/src/sys/process/unix/common.rs +++ b/library/std/src/sys/process/unix/common.rs @@ -218,7 +218,7 @@ impl Command { pub fn chroot(&mut self, dir: &Path) { self.chroot = Some(os2c(dir.as_os_str(), &mut self.saw_nul)); if self.cwd.is_none() { - self.cwd(&OsStr::new("/")); + self.cwd(OsStr::new("/")); } } pub fn setsid(&mut self, setsid: bool) { diff --git a/library/std/src/sys/process/unix/pidfd.rs b/library/std/src/sys/process/unix/pidfd.rs index ef8433068c967..c586354861dcd 100644 --- a/library/std/src/sys/process/unix/pidfd.rs +++ b/library/std/src/sys/process/unix/pidfd.rs @@ -2,7 +2,7 @@ use super::ExitStatus; use crate::io; use crate::os::fd::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use crate::sys::fd::FileDesc; -use crate::sys::{AsInner, FromInner, IntoInner, cvt}; +use crate::sys::{AsInner, FromInner, IntoInner, cvt, cvt_r}; #[cfg(test)] mod tests; @@ -61,7 +61,7 @@ impl PidFd { fn waitid(&self, options: libc::c_int) -> io::Result> { let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() }; - let r = cvt(unsafe { + let r = cvt_r(|| unsafe { libc::waitid(libc::P_PIDFD, self.0.as_raw_fd() as u32, &mut siginfo, options) }); match r { diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs index f64f6523d1432..311c7b0db2d90 100644 --- a/library/std/src/sys/sync/once/queue.rs +++ b/library/std/src/sys/sync/once/queue.rs @@ -60,7 +60,7 @@ use crate::sync::atomic::Ordering::{AcqRel, Acquire, Release}; use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr}; use crate::sync::once::OnceExclusiveState; use crate::thread::{self, Thread}; -use crate::{fmt, ptr, sync as public}; +use crate::{fmt, mem, ptr, sync as public}; type StateAndQueue = *mut (); @@ -237,6 +237,15 @@ impl Once { } } +/// A type to guard against the unwinds of stacks that nodes are located on due to panics. +struct PanicGuard; + +impl Drop for PanicGuard { + fn drop(&mut self) { + rtabort!("tried to drop node in intrusive list."); + } +} + fn wait( state_and_queue: &Atomic<*mut ()>, mut current: StateAndQueue, @@ -272,6 +281,9 @@ fn wait( continue; } + // Guard against unwinds using a `PanicGuard` that aborts when dropped. + let guard = PanicGuard; + // We have enqueued ourselves, now lets wait. // It is important not to return before being signaled, otherwise we // would drop our `Waiter` node and leave a hole in the linked list @@ -288,6 +300,9 @@ fn wait( unsafe { node.thread.park() } } + // The node was removed from the queue, disarm the guard. + mem::forget(guard); + return state_and_queue.load(Acquire); } } diff --git a/src/bootstrap/src/core/backend.rs b/src/bootstrap/src/core/backend.rs new file mode 100644 index 0000000000000..bc8c8eb650aef --- /dev/null +++ b/src/bootstrap/src/core/backend.rs @@ -0,0 +1,48 @@ +use std::str::FromStr; + +/// Represents a codegen backend. +#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] +pub enum CodegenBackendKind { + #[default] + Llvm, + Cranelift, + Gcc, + Custom(String), +} + +impl CodegenBackendKind { + /// Name of the codegen backend, as identified in the `compiler` directory + /// (`rustc_codegen_`). + pub(crate) fn name(&self) -> &str { + match self { + CodegenBackendKind::Llvm => "llvm", + CodegenBackendKind::Cranelift => "cranelift", + CodegenBackendKind::Gcc => "gcc", + CodegenBackendKind::Custom(name) => name, + } + } + + /// Name of the codegen backend's crate, e.g. `rustc_codegen_cranelift`. + pub(crate) fn crate_name(&self) -> String { + format!("rustc_codegen_{}", self.name()) + } + + pub(crate) fn is_llvm(&self) -> bool { + matches!(self, Self::Llvm) + } +} + +/// FIXME(Zalathar): This is partly redundant with the parsing code in `parse_codegen_backends`. +impl FromStr for CodegenBackendKind { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "" => Err("Invalid empty backend name"), + "gcc" => Ok(Self::Gcc), + "llvm" => Ok(Self::Llvm), + "cranelift" => Ok(Self::Cranelift), + _ => Ok(Self::Custom(s.to_string())), + } + } +} diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index ff16a814c456d..b8918ec12fd9f 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -3,6 +3,8 @@ use std::fs; use std::path::{Path, PathBuf}; +use crate::Mode; +use crate::core::backend::CodegenBackendKind; use crate::core::build_steps::compile::{ ArtifactKeepMode, add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_make_run, @@ -16,11 +18,11 @@ use crate::core::builder::{ self, Alias, Builder, Cargo, CommandLineStep, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description, }; +use crate::core::compiler::Compiler; use crate::core::config::TargetSelection; use crate::core::config::flags::Subcommand; use crate::utils::build_stamp::{self, BuildStamp}; use crate::utils::helpers::t; -use crate::{CodegenBackendKind, Compiler, Mode}; /// Allows individual check-step instances to keep track of whether they /// represent `cargo check` or `cargo fix`, independently of [`Builder::kind`]. diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index b7dae28c42ab3..a5c7398d11302 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -12,10 +12,11 @@ use std::path::Path; use crate::core::builder::{ Builder, CommandLineStep, Kind, RunConfig, ShouldRun, crate_description, }; +use crate::core::compiler::Compiler; use crate::core::config::flags::Subcommand; use crate::utils::build_stamp::BuildStamp; use crate::utils::helpers::t; -use crate::{Build, Compiler, Mode}; +use crate::{Build, Mode}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CleanAll {} diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs index 0d5dd410a57c6..2ca775f92d683 100644 --- a/src/bootstrap/src/core/build_steps/clippy.rs +++ b/src/bootstrap/src/core/build_steps/clippy.rs @@ -14,6 +14,7 @@ //! (as usual) a massive undertaking/refactoring. use super::tool::{SourceType, prepare_tool_cargo}; +use crate::Mode; use crate::core::build_steps::check::{CompilerForCheck, prepare_compiler_for_check}; use crate::core::build_steps::compile::{ ArtifactKeepMode, run_cargo, rustc_cargo, std_cargo, std_crates_for_make_run, @@ -22,11 +23,11 @@ use crate::core::builder::{ self, Alias, Builder, CommandLineStep, Kind, RunConfig, ShouldRun, StepMetadata, crate_description, }; +use crate::core::compiler::Compiler; use crate::core::config::TargetSelection; use crate::core::config::flags::Subcommand; use crate::utils::build_stamp::{self, BuildStamp}; use crate::utils::helpers; -use crate::{Compiler, Mode}; /// Disable the most spammy clippy lints const IGNORED_RULES_FOR_STD_AND_RUSTC: &[&str] = &[ @@ -590,6 +591,10 @@ impl CommandLineStep for CI { "clippy::ptr_offset_with_cast".into(), "clippy::let_and_return".into(), "clippy::needless_return".into(), + "clippy::needless_borrow".into(), + "clippy::op_ref".into(), + "clippy::borrow_deref_ref".into(), + "clippy::explicit_auto_deref".into(), ], forbid: vec![], }; diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 28043ec4fc3fb..3df27f5a8946b 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -19,6 +19,7 @@ use serde_derive::Deserialize; #[cfg(feature = "tracing")] use tracing::span; +use crate::core::backend::CodegenBackendKind; use crate::core::build_steps::gcc::{Gcc, GccOutput, GccTargetPair}; use crate::core::build_steps::llvm::{LlvmFromCi, prebuilt_llvm_output}; use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts}; @@ -27,6 +28,7 @@ use crate::core::builder::{ self, Builder, Cargo, CommandLineStep, Kind, RunConfig, ShouldRun, Step, StepMetadata, apply_pgo, crate_description, }; +use crate::core::compiler::Compiler; use crate::core::config::toml::target::DefaultLinuxLinkerOverride; use crate::core::config::{ Allocator, CompilerBuiltins, DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection, @@ -37,10 +39,7 @@ use crate::utils::exec::command; use crate::utils::helpers::{ self, exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date, }; -use crate::{ - CLang, CodegenBackendKind, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode, - debug, trace, -}; +use crate::{CLang, DependencyType, FileType, GitRepo, Mode, debug, trace}; /// Build a standard library for the given `target` using the given `build_compiler`. #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -2180,7 +2179,7 @@ impl CommandLineStep for Assemble { let _llvm_tools_span = span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin) .entered(); - for tool in LLVM_TOOLS { + for tool in dist::LLVM_TOOLS { trace!("installing `{tool}`"); let tool_exe = exe(tool, target_compiler.host); let src_path = llvm_bin_dir.join(&tool_exe); diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 3e42b6a5c725a..c99bdec73c349 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -19,6 +19,7 @@ use object::read::archive::ArchiveFile; #[cfg(feature = "tracing")] use tracing::instrument; +use crate::core::backend::CodegenBackendKind; use crate::core::build_steps::compile::{ get_codegen_backend_file, libgccjit_path_relative_to_cg_dir, normalize_codegen_backend_name, }; @@ -35,6 +36,7 @@ use crate::core::build_steps::{compile, llvm}; use crate::core::builder::{ Builder, CommandLineStep, Kind, RunConfig, ShouldRun, Step, StepMetadata, }; +use crate::core::compiler::Compiler; use crate::core::config::{GccCiMode, TargetSelection}; use crate::utils::build_stamp::{self, BuildStamp}; use crate::utils::channel::{self, Info}; @@ -43,7 +45,27 @@ use crate::utils::helpers::{ exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit, }; use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball}; -use crate::{CodegenBackendKind, Compiler, DependencyType, FileType, LLVM_TOOLS, Mode, trace}; +use crate::{DependencyType, FileType, Mode, trace}; + +pub(crate) const LLVM_TOOLS: &[&str] = &[ + "llvm-cov", // used to generate coverage report + "llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility + "llvm-objcopy", // used to transform ELFs into binary format which flashing tools consume + "llvm-objdump", // used to disassemble programs + "llvm-profdata", // used to inspect and merge files generated by profiles + "llvm-readobj", // used to get information from ELFs/objects that the other tools don't provide + "llvm-size", // used to prints the size of the linker sections of a program + "llvm-strip", // used to discard symbols from binary files to reduce their size + "llvm-ar", // used for creating and modifying archive files + "llvm-as", // used to convert LLVM assembly to LLVM bitcode + "llvm-dis", // used to disassemble LLVM bitcode + "llvm-link", // Used to link LLVM bitcode + "llc", // used to compile LLVM bytecode + "opt", // used to optimize LLVM bytecode +]; + +/// LLD file names for all flavors. +pub(crate) const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; pub fn pkgname(builder: &Builder<'_>, component: &str) -> String { format!("{}-{}", component, builder.rust_package_vers()) @@ -601,7 +623,7 @@ impl CommandLineStep for Rustc { let self_contained_lld_src_dir = src_dir.join("gcc-ld"); let self_contained_lld_dst_dir = dst_dir.join("gcc-ld"); t!(fs::create_dir(&self_contained_lld_dst_dir)); - for name in crate::LLD_FILE_NAMES { + for name in LLD_FILE_NAMES { let exe_name = exe(name, target_compiler.host); builder.copy_link( &self_contained_lld_src_dir.join(&exe_name), diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 21f1395351a80..adff654fe88e8 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -19,9 +19,10 @@ use crate::core::builder::{ self, Builder, CommandLineStep, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description, }; +use crate::core::compiler::Compiler; use crate::core::config::{Config, TargetSelection}; use crate::utils::helpers::{submodule_path_of, symlink_dir, t, up_to_date}; -use crate::{Compiler, FileType, Mode}; +use crate::{FileType, Mode}; macro_rules! book { ($($name:ident, $path:expr, $book_name:expr, $lang:expr ;)+) => { diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index 766c2cc0297d6..db0d18e8368e2 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -6,10 +6,10 @@ use std::path::{Component, Path, PathBuf}; use std::{env, fs}; -use crate::Compiler; use crate::core::build_steps::dist; use crate::core::build_steps::tool::RustcPrivateCompilers; use crate::core::builder::{Builder, CommandLineStep, Kind, RunConfig, ShouldRun}; +use crate::core::compiler::Compiler; use crate::core::config::{Config, TargetSelection}; use crate::utils::exec::command; use crate::utils::helpers::t; diff --git a/src/bootstrap/src/core/build_steps/synthetic_targets.rs b/src/bootstrap/src/core/build_steps/synthetic_targets.rs index 88f04dcb27c6e..2b5039214f62c 100644 --- a/src/bootstrap/src/core/build_steps/synthetic_targets.rs +++ b/src/bootstrap/src/core/build_steps/synthetic_targets.rs @@ -7,8 +7,8 @@ //! one of the target specs already defined in this module, or create new ones by adding a new step //! that calls create_synthetic_target. -use crate::Compiler; use crate::core::builder::{Builder, Step}; +use crate::core::compiler::Compiler; use crate::core::config::TargetSelection; #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index f59571ded126c..f0f246434d27b 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -15,6 +15,7 @@ use std::{env, fs, iter}; use build_helper::git::get_closest_upstream_commit; +use crate::core::backend::CodegenBackendKind; use crate::core::build_steps::compile::{ArtifactKeepMode, Std, run_cargo}; use crate::core::build_steps::doc::{DocumentationFormat, prepare_doc_compiler}; use crate::core::build_steps::format::InternalRustfmt; @@ -34,6 +35,7 @@ use crate::core::builder::{ self, Alias, Builder, CommandLineStep, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description, }; +use crate::core::compiler::Compiler; use crate::core::config::TargetSelection; use crate::core::config::flags::{Subcommand, get_completion, top_level_help}; use crate::core::{android, debuggers}; @@ -41,15 +43,33 @@ use crate::utils::build_stamp::{self, BuildStamp}; use crate::utils::exec::{BootstrapCommand, command}; use crate::utils::helpers::{ self, LldThreads, TestFilterCategory, add_dylib_path, add_rustdoc_cargo_linker_args, - dylib_path, dylib_path_var, linker_args, linker_flags, t, target_supports_cranelift_backend, - up_to_date, + dylib_path, dylib_path_var, envify, linker_args, linker_flags, t, + target_supports_cranelift_backend, up_to_date, }; use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests}; -use crate::{CLang, CodegenBackendKind, Compiler, GitRepo, Mode, TestTarget, envify}; +use crate::{CLang, GitRepo, Mode}; mod compiletest; pub mod failed_tests; +#[derive(PartialEq, Eq, Copy, Clone, Debug)] +pub enum TestTarget { + /// Run unit, integration and doc tests (default). + Default, + /// Run unit, integration, doc tests, examples, bins, benchmarks (no doc tests). + AllTargets, + /// Only run doc tests. + DocOnly, + /// Only run unit and integration tests. + Tests, +} + +impl TestTarget { + pub(crate) fn runs_doctests(&self) -> bool { + matches!(self, TestTarget::DocOnly | TestTarget::Default) + } +} + /// Runs `cargo test` on various internal tools used by bootstrap. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CrateBootstrap { diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 75d5fdcdd2c33..f74207fdd6d32 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -14,16 +14,18 @@ use std::path::{Path, PathBuf}; use std::{env, fs}; use crate::core::build_steps::compile::{CargoMessage, is_lto_stage}; +use crate::core::build_steps::dist::LLD_FILE_NAMES; use crate::core::build_steps::toolstate::ToolState; use crate::core::build_steps::{compile, llvm}; use crate::core::builder::{ self, Builder, Cargo as CargoCommand, CommandLineStep, Kind, RunConfig, ShouldRun, Step, StepMetadata, apply_pgo, cargo_profile_var, }; +use crate::core::compiler::Compiler; use crate::core::config::{Allocator, DebuginfoLevel, RustcLto, TargetSelection}; use crate::utils::exec::{BootstrapCommand, command}; use crate::utils::helpers::{self, add_dylib_path, exe, t}; -use crate::{Compiler, FileType, Mode}; +use crate::{FileType, Mode}; #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub enum SourceType { @@ -978,7 +980,7 @@ pub(crate) fn copy_lld_artifacts( let self_contained_lld_dir = libdir_bin.join("gcc-ld"); t!(fs::create_dir_all(&self_contained_lld_dir)); - for name in crate::LLD_FILE_NAMES { + for name in LLD_FILE_NAMES { builder.copy_link( &lld_wrapper.tool.tool_path, &self_contained_lld_dir.join(exe(name, target)), diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 6f7248011ec2a..7bd7c261f8067 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -1,21 +1,35 @@ -use std::env; use std::ffi::{OsStr, OsString}; use std::path::{Path, PathBuf}; +use std::sync::OnceLock; +use std::{env, fs}; use super::{Builder, Kind}; use crate::core::build_steps::llvm::prebuilt_llvm_output; use crate::core::build_steps::test; use crate::core::build_steps::tool::SourceType; +use crate::core::compiler::Compiler; use crate::core::config::flags::Color; use crate::core::config::toml::pgo::PgoConfig; use crate::core::config::{CompressDebuginfo, Config, DryRun, SplitDebuginfo, TargetSelection}; use crate::utils::build_stamp; use crate::utils::exec::{BootstrapCommand, command}; -use crate::utils::helpers::{self, LldThreads, check_cfg_arg, linker_flags, t}; -use crate::{ - CLang, Compiler, EXTRA_CHECK_CFGS, GitRepo, Mode, RemapScheme, envify, - prepare_behaviour_dump_dir, -}; +use crate::utils::helpers::{self, LldThreads, check_cfg_arg, envify, linker_flags, t}; +use crate::{CLang, GitRepo, Mode, RemapScheme}; + +/// Extra `--check-cfg` to add when building the compiler or tools +/// (Mode restriction, config name, config values (if any)) +#[expect(clippy::type_complexity)] // It's fine for hard-coded list and type is explained above. +const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ + (Some(Mode::Rustc), "bootstrap", None), + (Some(Mode::Codegen), "bootstrap", None), + (Some(Mode::ToolRustcPrivate), "bootstrap", None), + (Some(Mode::ToolStd), "bootstrap", None), + (Some(Mode::ToolRustcPrivate), "rust_analyzer", None), + (Some(Mode::ToolStd), "rust_analyzer", None), + // Any library specific cfgs like `target_os`, `target_arch` should be put in + // priority the `[lints.rust.unexpected_cfgs.check-cfg]` table + // in the appropriate `library/{std,alloc,core}/Cargo.toml` +]; /// Represents flag values in `String` form with a `\x1f` delimiter to pass to the compiler later. /// @@ -44,7 +58,7 @@ impl Rustflags { self.env(prefix); // ... and also handle target-specific env RUSTFLAGS if they're configured. - let target_specific = format!("CARGO_TARGET_{}_{}", crate::envify(&self.1.triple), prefix); + let target_specific = format!("CARGO_TARGET_{}_{}", envify(&self.1.triple), prefix); self.env(&target_specific); } @@ -1206,7 +1220,7 @@ impl Builder<'_> { } if self.config.dump_bootstrap_shims { - prepare_behaviour_dump_dir(self.build); + prepare_shims_dump_dir(self); cargo .env("DUMP_BOOTSTRAP_SHIMS", self.build.out.join("bootstrap-shims-dump")) @@ -1574,3 +1588,22 @@ pub fn apply_pgo( )); } } + +/// Ensures that the behavior dump directory is properly initialized. +fn prepare_shims_dump_dir(builder: &Builder<'_>) { + static INITIALIZED: OnceLock = OnceLock::new(); + + let dump_path = builder.out.join("bootstrap-shims-dump"); + + let initialized = INITIALIZED.get().unwrap_or(&false); + if !initialized { + // clear old dumps + if dump_path.exists() { + t!(fs::remove_dir_all(&dump_path)); + } + + t!(fs::create_dir_all(&dump_path)); + + t!(INITIALIZED.set(true)); + } +} diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 7b2e9670a6573..6871dea3e80e8 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -21,14 +21,16 @@ use crate::core::build_steps::{ }; use crate::core::builder::step_stack::StepRecord; pub use crate::core::builder::step_stack::StepStack; +use crate::core::compiler::Compiler; use crate::core::config::flags::Subcommand; use crate::core::config::{DryRun, TargetSelection}; +use crate::core::metadata::Crate; use crate::utils::build_stamp::BuildStamp; use crate::utils::cache::Cache; use crate::utils::exec::{BootstrapCommand, ExecutionContext, command}; use crate::utils::helpers::{self, LldThreads, add_dylib_path, exe, libdir, linker_args, t}; use crate::utils::tracing::format_location; -use crate::{Build, Compiler, Crate, trace}; +use crate::{Build, trace}; mod cargo; mod cli_paths; diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 49da1e165fb38..465c7d8a82726 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -359,10 +359,10 @@ fn any_debug() { /// These tests use insta for snapshot testing. /// See bootstrap's README on how to bless the snapshots. mod snapshot { - use crate::Compiler; use crate::core::build_steps::test; use crate::core::builder::tests::{RenderConfig, TEST_TRIPLE_1, TEST_TRIPLE_2, host_target}; use crate::core::builder::{Kind, StepMetadata}; + use crate::core::compiler::Compiler; use crate::core::config::TargetSelection; use crate::core::config::toml::target::{ DefaultLinuxLinkerOverride, with_default_linux_linker_overrides, diff --git a/src/bootstrap/src/core/compiler.rs b/src/bootstrap/src/core/compiler.rs new file mode 100644 index 0000000000000..a57c60465f24c --- /dev/null +++ b/src/bootstrap/src/core/compiler.rs @@ -0,0 +1,51 @@ +use std::hash::{Hash, Hasher}; + +use crate::Build; +use crate::core::config::TargetSelection; + +/// A structure representing a Rust compiler. +/// +/// Each compiler has a `stage` that it is associated with and a `host` that +/// corresponds to the platform the compiler runs on. +#[derive(Eq, PartialOrd, Ord, Clone, Copy, Debug)] +pub struct Compiler { + pub(crate) stage: u32, + pub(crate) host: TargetSelection, + /// Indicates whether the compiler was forced to use a specific stage. + /// This field is ignored in `Hash` and `PartialEq` implementations as only the `stage` + /// and `host` fields are relevant for those. + pub(crate) forced_compiler: bool, +} + +impl Hash for Compiler { + fn hash(&self, state: &mut H) { + self.stage.hash(state); + self.host.hash(state); + } +} + +impl PartialEq for Compiler { + fn eq(&self, other: &Self) -> bool { + self.stage == other.stage && self.host == other.host + } +} + +impl Compiler { + pub(crate) fn new(stage: u32, host: TargetSelection) -> Self { + Self { stage, host, forced_compiler: false } + } + + pub(crate) fn forced_compiler(&mut self, forced_compiler: bool) { + self.forced_compiler = forced_compiler; + } + + /// Returns `true` if this is a snapshot compiler for `build`'s configuration + pub(crate) fn is_snapshot(&self, build: &Build) -> bool { + self.stage == 0 && self.host == build.host_target + } + + /// Indicates whether the compiler was forced to use a specific stage. + pub(crate) fn is_forced_compiler(&self) -> bool { + self.forced_compiler + } +} diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index a9c9bb2f83167..071515ea78f1e 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -26,7 +26,7 @@ use serde::Deserialize; #[cfg(feature = "tracing")] use tracing::{instrument, span}; -use crate::CodegenBackendKind; +use crate::core::backend::CodegenBackendKind; use crate::core::build_steps::llvm; use crate::core::build_steps::llvm::{LLVM_INVALIDATION_PATHS, LlvmKind, LlvmOutput}; use crate::core::build_steps::test::failed_tests::collect_previously_failed_tests; diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index fa6225f6649e5..c8dbf8d4c4edf 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -10,13 +10,15 @@ use clap_complete::Generator; #[cfg(feature = "tracing")] use tracing::instrument; +use crate::Build; +use crate::core::backend::CodegenBackendKind; use crate::core::build_steps::perf::PerfArgs; use crate::core::build_steps::setup::Profile; +use crate::core::build_steps::test::TestTarget; use crate::core::builder::{Builder, Kind}; use crate::core::config::Config; use crate::core::config::target_selection::{TargetSelectionList, target_selection_list}; use crate::utils::helpers; -use crate::{Build, CodegenBackendKind, TestTarget}; #[derive(Copy, Clone, Default, Debug, ValueEnum)] pub enum Color { diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs index 86056d489911b..0c88a3d8d0172 100644 --- a/src/bootstrap/src/core/config/toml/rust.rs +++ b/src/bootstrap/src/core/config/toml/rust.rs @@ -7,7 +7,7 @@ use std::path::PathBuf; use build_helper::ci::CiEnv; use serde::{Deserialize, Deserializer}; -use crate::CodegenBackendKind; +use crate::core::backend::CodegenBackendKind; use crate::core::config::macros::define_config; use crate::core::config::toml::TomlConfig; use crate::core::config::{CompressDebuginfo, DebuginfoLevel, StringOrBool, TargetSelection}; @@ -430,6 +430,7 @@ pub fn check_incompatible_options_for_ci_rustc( pub(crate) const BUILTIN_CODEGEN_BACKENDS: &[&str] = &["llvm", "cranelift", "gcc"]; +/// FIXME(Zalathar): This is partly redundant with the parsing code in [`CodegenBackendKind`]. pub(crate) fn parse_codegen_backends( backends: Vec, section: &str, diff --git a/src/bootstrap/src/core/config/toml/target.rs b/src/bootstrap/src/core/config/toml/target.rs index 32e0477f11853..090ccefe700ca 100644 --- a/src/bootstrap/src/core/config/toml/target.rs +++ b/src/bootstrap/src/core/config/toml/target.rs @@ -15,7 +15,7 @@ use std::path::PathBuf; use serde::de::Error; use serde::{Deserialize, Deserializer}; -use crate::CodegenBackendKind; +use crate::core::backend::CodegenBackendKind; use crate::core::config::macros::define_config; use crate::core::config::{ Allocator, CompilerBuiltins, CompressDebuginfo, LlvmLibunwind, SplitDebuginfo, StringOrBool, diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs index 14f33ef9bdc5d..a3b52e1071d24 100644 --- a/src/bootstrap/src/core/metadata.rs +++ b/src/bootstrap/src/core/metadata.rs @@ -5,14 +5,29 @@ //! source, dependencies, targets, and available features. The collected metadata is then //! used to update the `Build` structure, ensuring proper dependency resolution and //! compilation flow. -use std::collections::BTreeMap; + +use std::collections::{BTreeMap, HashSet}; use std::path::PathBuf; use serde_derive::Deserialize; +use crate::Build; use crate::utils::exec::command; use crate::utils::helpers::t; -use crate::{Build, Crate}; + +#[derive(Debug, Clone)] +pub(crate) struct Crate { + pub(crate) name: String, + pub(crate) deps: HashSet, + pub(crate) path: PathBuf, + pub(crate) features: Vec, +} + +impl Crate { + pub(crate) fn local_path(&self, build: &Build) -> PathBuf { + self.path.strip_prefix(&build.config.src).unwrap().into() + } +} /// For more information, see the output of /// diff --git a/src/bootstrap/src/core/mod.rs b/src/bootstrap/src/core/mod.rs index 4df2ed319da68..d6db6c701cc35 100644 --- a/src/bootstrap/src/core/mod.rs +++ b/src/bootstrap/src/core/mod.rs @@ -1,6 +1,8 @@ pub(crate) mod android; +pub(crate) mod backend; pub(crate) mod build_steps; pub(crate) mod builder; +pub(crate) mod compiler; pub(crate) mod config; pub(crate) mod debuggers; pub(crate) mod download; diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index b574479c77e86..4c70be5bddc89 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -35,10 +35,13 @@ use termcolor::{ColorChoice, StandardStream, WriteColor}; use tracing::{instrument, span}; use crate::core::build_steps::format::InternalRustfmt; +use crate::core::build_steps::test::TestTarget; use crate::core::build_steps::vendor::VENDOR_DIR; use crate::core::builder::{Builder, Kind}; +use crate::core::compiler::Compiler; use crate::core::config::flags::{self, Subcommand}; use crate::core::config::{BootstrapOverrideLld, Config, DryRun, LlvmLibunwind, TargetSelection}; +use crate::core::metadata::Crate; use crate::utils::build_stamp::BuildStamp; use crate::utils::channel::GitInfo; use crate::utils::exec::{BootstrapCommand, ExecutionContext, command}; @@ -50,141 +53,6 @@ pub mod cli_main; mod core; mod utils; -const LLVM_TOOLS: &[&str] = &[ - "llvm-cov", // used to generate coverage report - "llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility - "llvm-objcopy", // used to transform ELFs into binary format which flashing tools consume - "llvm-objdump", // used to disassemble programs - "llvm-profdata", // used to inspect and merge files generated by profiles - "llvm-readobj", // used to get information from ELFs/objects that the other tools don't provide - "llvm-size", // used to prints the size of the linker sections of a program - "llvm-strip", // used to discard symbols from binary files to reduce their size - "llvm-ar", // used for creating and modifying archive files - "llvm-as", // used to convert LLVM assembly to LLVM bitcode - "llvm-dis", // used to disassemble LLVM bitcode - "llvm-link", // Used to link LLVM bitcode - "llc", // used to compile LLVM bytecode - "opt", // used to optimize LLVM bytecode -]; - -/// LLD file names for all flavors. -const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; - -/// Extra `--check-cfg` to add when building the compiler or tools -/// (Mode restriction, config name, config values (if any)) -#[expect(clippy::type_complexity)] // It's fine for hard-coded list and type is explained above. -const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ - (Some(Mode::Rustc), "bootstrap", None), - (Some(Mode::Codegen), "bootstrap", None), - (Some(Mode::ToolRustcPrivate), "bootstrap", None), - (Some(Mode::ToolStd), "bootstrap", None), - (Some(Mode::ToolRustcPrivate), "rust_analyzer", None), - (Some(Mode::ToolStd), "rust_analyzer", None), - // Any library specific cfgs like `target_os`, `target_arch` should be put in - // priority the `[lints.rust.unexpected_cfgs.check-cfg]` table - // in the appropriate `library/{std,alloc,core}/Cargo.toml` -]; - -/// A structure representing a Rust compiler. -/// -/// Each compiler has a `stage` that it is associated with and a `host` that -/// corresponds to the platform the compiler runs on. This structure is used as -/// a parameter to many methods below. -#[derive(Eq, PartialOrd, Ord, Clone, Copy, Debug)] -pub struct Compiler { - stage: u32, - host: TargetSelection, - /// Indicates whether the compiler was forced to use a specific stage. - /// This field is ignored in `Hash` and `PartialEq` implementations as only the `stage` - /// and `host` fields are relevant for those. - forced_compiler: bool, -} - -impl std::hash::Hash for Compiler { - fn hash(&self, state: &mut H) { - self.stage.hash(state); - self.host.hash(state); - } -} - -impl PartialEq for Compiler { - fn eq(&self, other: &Self) -> bool { - self.stage == other.stage && self.host == other.host - } -} - -/// Represents a codegen backend. -#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] -pub enum CodegenBackendKind { - #[default] - Llvm, - Cranelift, - Gcc, - Custom(String), -} - -impl CodegenBackendKind { - /// Name of the codegen backend, as identified in the `compiler` directory - /// (`rustc_codegen_`). - pub fn name(&self) -> &str { - match self { - CodegenBackendKind::Llvm => "llvm", - CodegenBackendKind::Cranelift => "cranelift", - CodegenBackendKind::Gcc => "gcc", - CodegenBackendKind::Custom(name) => name, - } - } - - /// Name of the codegen backend's crate, e.g. `rustc_codegen_cranelift`. - pub fn crate_name(&self) -> String { - format!("rustc_codegen_{}", self.name()) - } - - pub fn is_llvm(&self) -> bool { - matches!(self, Self::Llvm) - } - - pub fn is_cranelift(&self) -> bool { - matches!(self, Self::Cranelift) - } - - pub fn is_gcc(&self) -> bool { - matches!(self, Self::Gcc) - } -} - -impl std::str::FromStr for CodegenBackendKind { - type Err = &'static str; - - fn from_str(s: &str) -> Result { - match s.to_lowercase().as_str() { - "" => Err("Invalid empty backend name"), - "gcc" => Ok(Self::Gcc), - "llvm" => Ok(Self::Llvm), - "cranelift" => Ok(Self::Cranelift), - _ => Ok(Self::Custom(s.to_string())), - } - } -} - -#[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub enum TestTarget { - /// Run unit, integration and doc tests (default). - Default, - /// Run unit, integration, doc tests, examples, bins, benchmarks (no doc tests). - AllTargets, - /// Only run doc tests. - DocOnly, - /// Only run unit and integration tests. - Tests, -} - -impl TestTarget { - fn runs_doctests(&self) -> bool { - matches!(self, TestTarget::DocOnly | TestTarget::Default) - } -} - pub enum GitRepo { Rustc, Llvm, @@ -260,20 +128,6 @@ pub struct Build { step_graph: std::cell::RefCell, } -#[derive(Debug, Clone)] -struct Crate { - name: String, - deps: HashSet, - path: PathBuf, - features: Vec, -} - -impl Crate { - fn local_path(&self, build: &Build) -> PathBuf { - self.path.strip_prefix(&build.config.src).unwrap().into() - } -} - /// When building Rust various objects are handled differently. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum DependencyType { @@ -2024,54 +1878,3 @@ fn chmod(path: &Path, perms: u32) { } #[cfg(windows)] fn chmod(_path: &Path, _perms: u32) {} - -impl Compiler { - pub fn new(stage: u32, host: TargetSelection) -> Self { - Self { stage, host, forced_compiler: false } - } - - pub fn forced_compiler(&mut self, forced_compiler: bool) { - self.forced_compiler = forced_compiler; - } - - /// Returns `true` if this is a snapshot compiler for `build`'s configuration - pub fn is_snapshot(&self, build: &Build) -> bool { - self.stage == 0 && self.host == build.host_target - } - - /// Indicates whether the compiler was forced to use a specific stage. - pub fn is_forced_compiler(&self) -> bool { - self.forced_compiler - } -} - -fn envify(s: &str) -> String { - // Converting foo-bar to FOO_BAR is a fairly idomatic mapping to an environment variable name. - // We also convert '.' to '_' to fix https://github.com/rust-lang/rust/issues/158090 - s.chars() - .map(|c| match c { - '-' | '.' => '_', - c => c, - }) - .flat_map(|c| c.to_uppercase()) - .collect() -} - -/// Ensures that the behavior dump directory is properly initialized. -pub fn prepare_behaviour_dump_dir(build: &Build) { - static INITIALIZED: OnceLock = OnceLock::new(); - - let dump_path = build.out.join("bootstrap-shims-dump"); - - let initialized = INITIALIZED.get().unwrap_or(&false); - if !initialized { - // clear old dumps - if dump_path.exists() { - t!(fs::remove_dir_all(&dump_path)); - } - - t!(fs::create_dir_all(&dump_path)); - - t!(INITIALIZED.set(true)); - } -} diff --git a/src/bootstrap/src/utils/build_stamp.rs b/src/bootstrap/src/utils/build_stamp.rs index de7f4c7343c5e..d27d5fa2cf420 100644 --- a/src/bootstrap/src/utils/build_stamp.rs +++ b/src/bootstrap/src/utils/build_stamp.rs @@ -7,10 +7,12 @@ use std::{fs, io}; use sha2::digest::Digest; +use crate::Mode; +use crate::core::backend::CodegenBackendKind; use crate::core::builder::Builder; +use crate::core::compiler::Compiler; use crate::core::config::TargetSelection; use crate::utils::helpers::{self, hex_encode, mtime, t}; -use crate::{CodegenBackendKind, Compiler, Mode}; #[cfg(test)] mod tests; diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 021763fdb371a..8e881f1bf7734 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -571,6 +571,25 @@ pub fn set_file_times>(path: P, times: fs::FileTimes) -> io::Resu f.set_times(times) } +/// Converts a target-tuple or other string into +/// [the form expected by cargo environment variable names][cargo-env]. +/// +/// For example: +/// - `x86_64-unknown-linux-gnu` => `X86_64_UNKNOWN_LINUX_GNU`. +/// +/// [cargo-env]: https://doc.rust-lang.org/cargo/reference/config.html#environment-variables +pub(crate) fn envify(s: &str) -> String { + // Converting foo-bar to FOO_BAR is a fairly idomatic mapping to an environment variable name. + // We also convert '.' to '_' to fix https://github.com/rust-lang/rust/issues/158090 + s.chars() + .map(|c| match c { + '-' | '.' => '_', + c => c, + }) + .flat_map(|c| c.to_uppercase()) + .collect() +} + /// Exits the process by calling [`std::process::exit`]. /// /// In CI, extra information will be printed to make failures easier to investigate. diff --git a/src/bootstrap/src/utils/helpers/tests.rs b/src/bootstrap/src/utils/helpers/tests.rs index cfb1dde2d6ea3..53d56169eb03e 100644 --- a/src/bootstrap/src/utils/helpers/tests.rs +++ b/src/bootstrap/src/utils/helpers/tests.rs @@ -3,8 +3,8 @@ use std::io::Write; use std::path::PathBuf; use crate::utils::helpers::{ - check_cfg_arg, extract_beta_rev, hex_encode, make, set_file_times, submodule_path_of_paths, - symlink_dir, + check_cfg_arg, envify, extract_beta_rev, hex_encode, make, set_file_times, + submodule_path_of_paths, symlink_dir, }; use crate::utils::tests::TestCtx; @@ -119,3 +119,21 @@ fn test_submodule_path_of() { // Make sure paths that only share a string prefix with a submodule are not matched. assert_eq!(submodule_path_of_paths(&submodules, "src/tools/cargo-vendor"), None); } + +#[test] +fn test_envify() { + struct Case { + input: &'static str, + expected: &'static str, + } + let cases = &[ + Case { input: "x86_64-unknown-linux-gnu", expected: "X86_64_UNKNOWN_LINUX_GNU" }, + // Arbitrary target containing `.` from the tier-3 target list. + Case { input: "thumbv8m.base-none-eabi", expected: "THUMBV8M_BASE_NONE_EABI" }, + ]; + + for &Case { input, expected } in cases { + let actual = envify(input); + assert_eq!(actual, expected, "input = {input:?}"); + } +} diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/dist.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/dist.sh index f2f78b04d7787..ba1ed57491070 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/dist.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/dist.sh @@ -19,4 +19,16 @@ if [ "${DIST_TRY_BUILD:-0}" == "0" ]; then CC=/rustroot/bin/cc CXX=/rustroot/bin/c++ python3 ../x.py dist \ gcc-dev \ gcc + # We confirm that the built GCC has support for the `retain` attribute. + # FIXME: Maybe get the path from `.x.py` instead? + gcc_path="./build/$HOSTS/gcc/$HOSTS/install/bin/gcc" + c_code='int x __attribute__((used, retain));' + if echo "$c_code" | "$gcc_path" -S -x c -o - - | grep -i '"a.*R"'; then + echo "retain attribute is supported" + else + echo "retain attribute is not supported" + # We display the generated asm just in case... + echo "$c_code" | "$gcc_path" -S -x c -o - - + exit 1 + fi fi diff --git a/src/ci/docker/scripts/build-gcc.sh b/src/ci/docker/scripts/build-gcc.sh index 6a96b82d3f924..c1c94a89d17e7 100755 --- a/src/ci/docker/scripts/build-gcc.sh +++ b/src/ci/docker/scripts/build-gcc.sh @@ -4,6 +4,27 @@ set -eux source shared.sh +# We have to build our own binutils for the GCC build, because the default CentOS 7 binutils are +# too old, and they do not support `SHF_GNU_RETAIN`. +BINUTILS="2.47" +curl https://ci-mirrors.rust-lang.org/rustc/gcc/binutils-$BINUTILS.tar.xz | xzcat | tar xf - +mkdir binutils-build +cd binutils-build +hide_output ../binutils-$BINUTILS/configure --prefix=/rustroot +hide_output make -j$(nproc) +hide_output make install + +cd .. +rm -rf binutils-build binutils-$BINUTILS + +if echo '.section .test,"awR",@progbits' | as - -o /dev/null 2>/dev/null; then + echo "binutils assembler supports SHF_GNU_RETAIN" +else + echo "binutils assembler DOES NOT support SHF_GNU_RETAIN" + exit 1 +fi + + # Note: in the future when bumping to version 10.1.0, also take care of the sed block below. # This version is specified in the Dockerfile GCC=$GCC_VERSION @@ -36,6 +57,7 @@ sed -i'' 's|ftp://gcc\.gnu\.org/pub/gcc/infrastructure|https://ci-mirrors.rust-l mkdir ../gcc-build cd ../gcc-build +export PATH=/rustroot/bin:$PATH # '-fno-reorder-blocks-and-partition' is required to # enable BOLT optimization of the C++ standard library, # which is included in librustc_driver.so diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index e7c33c13e2cf1..08121a9a693b7 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -312,7 +312,7 @@ auto: - name: dist-x86_64-illumos <<: *job-linux-4c - - <<: [*job-dist-x86_64-linux, *job-linux-36c-codebuild] + - <<: [*job-dist-x86_64-linux, *job-linux-32c-ec2] - name: dist-x86_64-linux-alt env: diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index bedfa65ac894d..b9c79ab0128e9 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -87,6 +87,7 @@ - [\*-unknown-l4re](platform-support/l4re.md) - [\*-unknown-trusty](platform-support/trusty.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) + - [bpf\*-unknown-none](platform-support/bpf-unknown-none.md) - [csky-unknown-linux-gnuabiv2\*](platform-support/csky-unknown-linux-gnuabiv2.md) - [hexagon-unknown-linux-musl](platform-support/hexagon-unknown-linux-musl.md) - [hexagon-unknown-none-elf](platform-support/hexagon-unknown-none-elf.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index c8ae02b091034..2643c7fd12891 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -330,8 +330,8 @@ target | std | host | notes [`armv7a-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX [`armv7a-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX, hardfloat [`avr-none`](platform-support/avr-none.md) | * | | AVR; requires `-Zbuild-std=core` and `-Ctarget-cpu=...` -`bpfeb-unknown-none` | * | | BPF (big endian) -`bpfel-unknown-none` | * | | BPF (little endian) +[`bpfeb-unknown-none`](platform-support/bpf-unknown-none.md) | * | | BPF (big endian) +[`bpfel-unknown-none`](platform-support/bpf-unknown-none.md) | * | | BPF (little endian) [`csky-unknown-linux-gnuabiv2`](platform-support/csky-unknown-linux-gnuabiv2.md) | ✓ | | C-SKY abiv2 Linux (little endian) [`csky-unknown-linux-gnuabiv2hf`](platform-support/csky-unknown-linux-gnuabiv2.md) | ✓ | | C-SKY abiv2 Linux, hardfloat (little endian) [`hexagon-unknown-linux-musl`](platform-support/hexagon-unknown-linux-musl.md) | ✓ | | Hexagon Linux with musl 1.2.5 diff --git a/src/doc/rustc/src/platform-support/bpf-unknown-none.md b/src/doc/rustc/src/platform-support/bpf-unknown-none.md new file mode 100644 index 0000000000000..4b1d46e0b41d7 --- /dev/null +++ b/src/doc/rustc/src/platform-support/bpf-unknown-none.md @@ -0,0 +1,171 @@ +# `bpf*-unknown-none` + +**Tier: 3** + +* `bpfeb-unknown-none` (big endian) +* `bpfel-unknown-none` (little endian) + +Targets for the 64-bit [BPF virtual machine][ebpf]. + +## Target maintainers + +[@nagisa](https://github.com/nagisa) [@vadorovsky](https://github.com/vadorovsky) + +## Requirements + +BPF targets require a Rust toolchain with the `rust-src` component. In +addition, you must install the [bpf-linker]. + +They don't support std and alloc and are meant for a `no_std` environment. + +`extern "C"` uses the [BPF ABI calling convention][bpf-abi]. + +Produced binaries use the ELF format. + +BPF virtual machines provide a [JIT compiler][jit] that compiles the BPF +bytecode into the native host architecture. + +Running BPF programs on most host architectures requires Linux kernel 4.18, +[that introduced BTF][linux-commit-btf], or newer. On RISC-V hosts that +requirement goes up to [5.7][linux-commit-riscv], on PowerPC32 - to [5.13] +[linux-commit-ppc32], and on LoongArch - to [6.1][linux-commit-loongarch]. + +## Building the target + +You can build Rust with support for BPF targets by adding them to the `target` +list in `config.toml`: + +```toml +[build] +target = ["bpfeb-unknown-none", "bpfel-unknown-none"] +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy of `core` by using +`build-std` or similar. + +Building the BPF target requires specifying it explicitly. Users can either +add it to the `target` list in `config.toml`: + +```toml +[build] +target = ["bpfel-unknown-none"] +``` + +Or specify it directly in the `cargo build` invocation: + +```console +cargo +nightly build -Z build-std=core --target bpfel-unknown-none +``` + +BPF has its own debug info format called [BTF][btf]. + +BPF targets use [bpf-linker], an LLVM bitcode linker. In future, they may +migrate to the GNU flavor of linker, see the details in the [following issue] +[bpf-object-linking]. + +## Error handling + +There is no concept of stack unwinding in BPF, therefore BPF programs are +expected to handle errors in a recoverable manner. Therefore most BPF programs +written in Rust use the following panic handler implementation: + +```rust,ignore (a panic handler implementation specific to BPF targets) +#[cfg(not(test))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} +``` + +Infinite loops are forbidden by the BPF verifier. Therefore, if the program +contains any code which can panic, the BPF VM refuses to load it. + +## Testing + +BPF bytecode needs to be executed on a BPF virtual machine, like the one +provided by the Linux kernel or one of the user-space implementations like +[rbpf][rbpf]. None of them support running Rust `#[test]` functions. One of the +reasons is the lack of support for panicking. + +Therefore, unit tests need to run on the host system. That requirement can be +enforced by the following conditional check: + +```rust +#[cfg(all(not(target_arch = "bpf"), test))] +mod test {} +``` + +## Cross-compilation toolchains + +BPF programs are always cross-compiled from a host (e.g. +`x86_64-unknown-linux-*`) for a BPF target (e.g. `bpfel-unknown-none`). + +The endianness of a chosen BPF target needs to match the endianness of the BPF +VM host on which the program is supposed to run. + +The architecture of the BPF VM host often has an impact on types that the BPF +programs should use. For example [kprobes][kprobe], [fprobes][fprobe] and +[uprobes][uprobe] allow dynamic function tracing and lookup into host registers +through the [`pt_regs`][pt-regs] struct, which differs across architectures. + +That difference is still not a concern of the compiler. Instead, it should be +handled by the developers. [Aya][aya] (the library for writing Linux BPF +programs and the main consumer of BPF targets in Rust) handles that by +providing the [`aya-ebpf-cty`][aya-ebpf-cty] crate, with type aliases similar +to those provided by [`core:ffi`][core-ffi]. [`aya-ebpf-cty`][aya-ebpf-cty] +allows to specify the VM target through the `CARGO_CFG_BPF_TARGET_ARCH` +environment variable (e.g. `CARGO_CFG_BPF_TARGET_ARCH=aarch64`). + +## C code + +It's possible to link a Rust BPF project to bitcode or object files which are +built from C code with [clang][clang]. It can be done using a `rustc-link-lib` +instruction in `build.rs`. Example: + +```rust,no_run +use std::{env, process::Command}; + +let out_dir = env::var("OUT_DIR").unwrap(); +let c_module = "my_module.bpf.c"; +let s = Command::new("clang") + .arg("-I") + .arg("src/") + .arg("-O2") + .arg("-emit-llvm") + .arg("-target") + .arg("bpf") + .arg("-c") + .arg("-g") + .arg(c_module) + .arg("-o") + .arg(format!("{out_dir}/my_module.bpf.o")) + .status() + .unwrap(); +assert!(s.success()); +println!("cargo:rustc-link-search=native={out_dir}"); +println!("cargo:rustc-link-lib=link-arg={out_dir}/my_module.bpf.o"); +``` + +[ebpf]: https://ebpf.io/ +[bpf-linker]: https://github.com/aya-rs/bpf-linker +[bpf-abi]: https://www.kernel.org/doc/html/v6.13/bpf/standardization/abi.html +[jit]: https://www.kernel.org/doc/html/v6.13/networking/filter.html#jit-compiler +[linux-commit-btf]: https://github.com/torvalds/linux/commit/69b693f0a +[linux-commit-riscv]: https://github.com/torvalds/linux/commit/5f316b65e +[linux-commit-ppc32]: https://github.com/torvalds/linux/commit/51c66ad84 +[linux-commit-loongarch]: https://github.com/torvalds/linux/commit/5dc615520 +[btf]: https://www.kernel.org/doc/html/v6.13/bpf/btf.html +[bpf-object-linking]: https://github.com/rust-lang/rust/issues/135175 +[rbpf]: https://github.com/qmonnet/rbpf +[kprobe]: https://www.kernel.org/doc/html/v6.13/trace/kprobes.html +[fprobe]: https://www.kernel.org/doc/html/v6.13/trace/fprobe.html +[uprobe]: https://www.kernel.org/doc/html/v6.13/trace/uprobetracer.html +[pt-regs]: https://elixir.bootlin.com/linux/v6.12.6/source/arch/x86/include/uapi/asm/ptrace.h#L44 +[aya]: https://aya-rs.dev +[aya-ebpf-cty]: https://github.com/aya-rs/aya/tree/main/ebpf/aya-ebpf-cty +[core-ffi]: https://doc.rust-lang.org/stable/core/ffi/index.html +[clang]: https://clang.llvm.org/ diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 976d7e39d4ddd..8584e0aff0538 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -5301,7 +5301,7 @@ async function showResults(docSearch, results, goToFirst, filterCrates) { } const crateSearch = document.getElementById("crate-search"); if (crateSearch) { - // #crate-search is an input element + // #crate-search is a `"). +assert-text: (".search-switcher", "Search results in all crates", STARTS_WITH) + +// Checking the display of the crate filter. +// We start with the light theme. +call-function: ("switch-theme", {"theme": "light"}) + +set-timeout: 2000 +wait-for: "#crate-search" +assert-css: ("#crate-search", { + "border": "1px solid #e0e0e0", + "color": "black", + "background-color": "white", +}) + +// We now check the dark theme. +call-function: ("switch-theme", {"theme": "dark"}) +wait-for-css: ("#crate-search", { + "border": "1px solid #e0e0e0", + "color": "#ddd", + "background-color": "#353535", +}) + +// And finally we check the ayu theme. +call-function: ("switch-theme", {"theme": "ayu"}) +wait-for-css: ("#crate-search", { + "border": "1px solid #5c6773", + "color": "#c5c5c5", + "background-color": "#0f1419", +}) diff --git a/tests/ui/const-generics/generic_const_exprs/const-generics-closure.stderr b/tests/ui/const-generics/generic_const_exprs/const-generics-closure.stderr index 5410bbdc12536..3ab2d6676724b 100644 --- a/tests/ui/const-generics/generic_const_exprs/const-generics-closure.stderr +++ b/tests/ui/const-generics/generic_const_exprs/const-generics-closure.stderr @@ -7,7 +7,7 @@ LL | let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<& = note: see issue #97362 for more information = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: consider removing `for<...>` + = help: consider using a type annotation instead: `let closure: for<...> fn(...) -> ... = /* closure */;` error[E0308]: mismatched types --> $DIR/const-generics-closure.rs:4:10 diff --git a/tests/ui/consts/promotion-drop-type-static-lifetime-86672.rs b/tests/ui/consts/promotion-drop-type-static-lifetime-86672.rs new file mode 100644 index 0000000000000..5fc8d06708451 --- /dev/null +++ b/tests/ui/consts/promotion-drop-type-static-lifetime-86672.rs @@ -0,0 +1,23 @@ +// Regression test for . +// Borrowing an array of a Drop type in a const used to fail with E0493 and E0716 +// unless the borrow went through another const. +//@ check-pass + +#![allow(dead_code)] + +pub struct Foo<'a, B: ?Sized>(&'a B); + +struct Bar; +impl Drop for Bar { + fn drop(&mut self) {} +} + +// These always worked. +const BAR0: Bar = Bar; +const BAR1: &'static [Bar] = &[Bar]; +const BAR2: Foo<'static, [Bar]> = Foo(BAR1); +// These used to fail. +const BAR3: Foo<'static, [Bar]> = Foo(&[Bar]); +const BAR4: Foo<'static, [Bar]> = Foo(&[Bar] as &'static [Bar]); + +fn main() {} diff --git a/tests/ui/expr/malformed_closure/missing-braces-before-close-brace.stderr b/tests/ui/expr/malformed_closure/missing-braces-before-close-brace.stderr index baf6a9dd9f4c9..533c1432611a3 100644 --- a/tests/ui/expr/malformed_closure/missing-braces-before-close-brace.stderr +++ b/tests/ui/expr/malformed_closure/missing-braces-before-close-brace.stderr @@ -27,7 +27,7 @@ LL | for<> || -> () {}; = note: see issue #97362 for more information = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: consider removing `for<...>` + = help: consider using a type annotation instead: `let closure: for<...> fn(...) -> ... = /* closure */;` error[E0658]: `for<...>` binders for closures are experimental --> $DIR/missing-braces-before-close-brace.rs:6:5 @@ -38,7 +38,7 @@ LL | for<'a> || -> () |_; = note: see issue #97362 for more information = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: consider removing `for<...>` + = help: consider using a type annotation instead: `let closure: for<...> fn(...) -> ... = /* closure */;` error: aborting due to 5 previous errors diff --git a/tests/ui/feature-gates/feature-gate-closure_lifetime_binder.stderr b/tests/ui/feature-gates/feature-gate-closure_lifetime_binder.stderr index 96e428fb9a37e..d5306287b58d9 100644 --- a/tests/ui/feature-gates/feature-gate-closure_lifetime_binder.stderr +++ b/tests/ui/feature-gates/feature-gate-closure_lifetime_binder.stderr @@ -7,7 +7,7 @@ LL | for<> || -> () {}; = note: see issue #97362 for more information = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: consider removing `for<...>` + = help: consider using a type annotation instead: `let closure: for<...> fn(...) -> ... = /* closure */;` error[E0658]: `for<...>` binders for closures are experimental --> $DIR/feature-gate-closure_lifetime_binder.rs:4:5 @@ -18,7 +18,7 @@ LL | for<'a> || -> () {}; = note: see issue #97362 for more information = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: consider removing `for<...>` + = help: consider using a type annotation instead: `let closure: for<...> fn(...) -> ... = /* closure */;` error[E0658]: `for<...>` binders for closures are experimental --> $DIR/feature-gate-closure_lifetime_binder.rs:6:5 @@ -29,7 +29,7 @@ LL | for<'a, 'b> |_: &'a ()| -> () {}; = note: see issue #97362 for more information = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: consider removing `for<...>` + = help: consider using a type annotation instead: `let closure: for<...> fn(...) -> ... = /* closure */;` error: aborting due to 3 previous errors diff --git a/tests/ui/imports/auxiliary/pathloop.rs b/tests/ui/imports/auxiliary/pathloop.rs new file mode 100644 index 0000000000000..f69f0e0c8c056 --- /dev/null +++ b/tests/ui/imports/auxiliary/pathloop.rs @@ -0,0 +1,6 @@ +pub struct AStruct; + +pub mod prelude { + pub use crate as pathloop; + pub use crate::AStruct; +} diff --git a/tests/ui/imports/path-with-infinite-visible-names-57500.rs b/tests/ui/imports/path-with-infinite-visible-names-57500.rs new file mode 100644 index 0000000000000..74a3bb1969b19 --- /dev/null +++ b/tests/ui/imports/path-with-infinite-visible-names-57500.rs @@ -0,0 +1,12 @@ +// Regression test for . +// An item reachable under infinitely many paths used to hang path printing +// while rendering this error. +//@ aux-build: pathloop.rs + +extern crate pathloop; + +use pathloop::prelude::*; + +fn main() { + let _x: AStruct = 42; //~ ERROR mismatched types +} diff --git a/tests/ui/imports/path-with-infinite-visible-names-57500.stderr b/tests/ui/imports/path-with-infinite-visible-names-57500.stderr new file mode 100644 index 0000000000000..2f7b1e6ad106c --- /dev/null +++ b/tests/ui/imports/path-with-infinite-visible-names-57500.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/path-with-infinite-visible-names-57500.rs:11:23 + | +LL | let _x: AStruct = 42; + | ------- ^^ expected `AStruct`, found integer + | | + | expected due to this + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/recover/recover-quantified-closure.stderr b/tests/ui/parser/recover/recover-quantified-closure.stderr index 96953b7beeede..095657882c36c 100644 --- a/tests/ui/parser/recover/recover-quantified-closure.stderr +++ b/tests/ui/parser/recover/recover-quantified-closure.stderr @@ -13,7 +13,7 @@ LL | for<'a> |x: &'a u8| *x + 1; = note: see issue #97362 for more information = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: consider removing `for<...>` + = help: consider using a type annotation instead: `let closure: for<...> fn(...) -> ... = /* closure */;` error[E0658]: `for<...>` binders for closures are experimental --> $DIR/recover-quantified-closure.rs:10:5 @@ -24,7 +24,7 @@ LL | for ::Bar in x {} = note: see issue #97362 for more information = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: consider removing `for<...>` + = help: consider using a type annotation instead: `let closure: for<...> fn(...) -> ... = /* closure */;` error: implicit types in closure signatures are forbidden when `for<...>` is present --> $DIR/recover-quantified-closure.rs:3:24 diff --git a/yarn.lock b/yarn.lock index c62a4c75f949b..55c862d1e75dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -74,12 +74,12 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@puppeteer/browsers@3.0.6": - version "3.0.6" - resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-3.0.6.tgz#6b772e0fc11deb255c8a3c14219e34a16a2ab23d" - integrity sha512-B/gKoqlFkzhvzsI6jo9K1cZz9o5ypviVv/xu8CwA4grZzyVwN+XfkT+tu8T1zrauuEXv6VhS2oGX+6NL95WcKA== +"@puppeteer/browsers@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-3.2.0.tgz#269293687a4c701a0a4701a15b50e9c0e337de93" + integrity sha512-LlBrE8oqGfU7b1Nk2d5Q1SbuPhZxTj0cJEMDPEws28OjNMELlflekmPPuf4FnK03x0ZRjKaYwJElUcKK4kyqJA== dependencies: - modern-tar "^0.7.6" + modern-tar "^0.8.0" yargs "^18.0.0" "@ungap/structured-clone@^1.2.0": @@ -113,9 +113,9 @@ ansi-regex@^5.0.1: integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-regex@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" - integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + version "6.3.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.3.0.tgz#247c8e7b70a1a43b10ce14c0226fcbf58e8815d5" + integrity sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ== ansi-styles@^4.1.0: version "4.3.0" @@ -155,9 +155,9 @@ braces@^3.0.3: fill-range "^7.1.1" browser-ui-test@^0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/browser-ui-test/-/browser-ui-test-0.25.0.tgz#e24352d63009f07ec42583c96330a1ca57487d88" - integrity sha512-DBSpC3UFzQTKhj9cc11AiRliCUiWut1GAJ6sLPEYYPCmF6gTQGg/eynwev0NXPiDpuawiVxSpXPttHQePRK6Ug== + version "0.25.1" + resolved "https://registry.yarnpkg.com/browser-ui-test/-/browser-ui-test-0.25.1.tgz#c7f22a5e2b9e51be4ba34df3adf7bd7a9249bce6" + integrity sha512-woRwKU1dPBIwYmCI6npox8qlPO0WQ8GZH2YbL39mNkiWymByebiB4EK0PlaGMbmEja0MEqfMQD+d33LCW4S2AA== dependencies: css-unit-converter "^1.1.2" pngjs "^3.4.0" @@ -237,10 +237,10 @@ deep-is@^0.1.3: resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -devtools-protocol@0.0.1653615: - version "0.0.1653615" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1653615.tgz#c600e0c619612156b2422a66d958ba188d87dbe8" - integrity sha512-pGVkY3T/qXxAp2nFPodwYqOevk6ncNMSmvL8QfRCx5ZWGd6Vor7AFNmyaA8Zs6uJyP1QAfjuLandCgvSix1BNA== +devtools-protocol@0.0.1666840: + version "0.0.1666840" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1666840.tgz#796cbc307f82750afc13a3b471c829bf3da19a65" + integrity sha512-gCcO42XCHKEs7Ag0S7aGYsnJ7hlgrO3qderYqeiY0Eqk+0GFfuvT13IA0hHreJTa2KCdDVyGMeOhdMNmrrTjVg== doctrine@^3.0.0: version "3.0.0" @@ -626,10 +626,10 @@ mitt@^3.0.1: resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1" integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== -modern-tar@^0.7.6: - version "0.7.7" - resolved "https://registry.yarnpkg.com/modern-tar/-/modern-tar-0.7.7.tgz#ca71d79603630076b10733b0751ccab284bbc1ef" - integrity sha512-t9VmxaqrmANnEOBhpSDI6HD192Ge48k8vmWqQQL7hSFEqHEYwZbbsu49+aKLWZeRvFs3j1pMhXOqqF4kPlvjkQ== +modern-tar@^0.8.0: + version "0.8.4" + resolved "https://registry.yarnpkg.com/modern-tar/-/modern-tar-0.8.4.tgz#25d2de2f522250012f33a3b366400b49741f6b8e" + integrity sha512-gN54ddmyzEg10orwZ2u4OOv+bjpMWdIl5jIkodK97bMq8QBSL5c0D7YX0lT1Ooz+99S7+PvFbnxzdjgHo1r41g== ms@^2.1.3: version "2.1.3" @@ -716,28 +716,28 @@ punycode@^2.1.0: resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -puppeteer-core@25.4.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-25.4.0.tgz#2fcba53a9ab94d55f196e1e42dbe794bbadf8759" - integrity sha512-K1plkLOdeoUnGeT1OvdqF3qxl33v+Ra/uH5VyPEhXdMcpvGiEskHzxxEU3fgpccJpJLIipB/rPUsvkZRWeKqOA== +puppeteer-core@25.7.0: + version "25.7.0" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-25.7.0.tgz#e1a31698ec4646ecf891de42636d6f6405945625" + integrity sha512-wgBBj7dU5ceGyoT2PCrJpkYOhxPY8mDOmcSKZP92Cj5GgqQ3kv/UxzawnOLxiYuupe4bDf/yiQm3bzs/1nI0rQ== dependencies: - "@puppeteer/browsers" "3.0.6" + "@puppeteer/browsers" "3.2.0" chromium-bidi "17.0.2" - devtools-protocol "0.0.1653615" + devtools-protocol "0.0.1666840" typed-query-selector "^2.12.2" webdriver-bidi-protocol "0.4.2" ws "^8.21.1" puppeteer@^25.1.0: - version "25.4.0" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-25.4.0.tgz#87b549a666ffc4f68fee2f195c42d67eba9b8168" - integrity sha512-xfQp8dFBcGaLc1hEMaVr7s+oW4ZkAurr8Y9H81ilKhu6QoLfSTkZjU7IavnyJ/VWpB9ni3KNJUQHUatslLWyGw== + version "25.7.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-25.7.0.tgz#4536e40b3685309b9f8444860d237d6be3484c83" + integrity sha512-zLBIYuW66SGwY7JNqGmiqeKiM92CYOs6xPibSRBPIeYGIfM1nE/8VCE8G0fGot2EfXENC4PbhktxLrQ0EK5Thg== dependencies: - "@puppeteer/browsers" "3.0.6" + "@puppeteer/browsers" "3.2.0" chromium-bidi "17.0.2" - devtools-protocol "0.0.1653615" + devtools-protocol "0.0.1666840" lilconfig "^3.1.3" - puppeteer-core "25.4.0" + puppeteer-core "25.7.0" typed-query-selector "^2.12.2" queue-microtask@^1.2.2: @@ -902,9 +902,9 @@ wrappy@1: integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== ws@^8.21.1: - version "8.21.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.21.1.tgz#045650cd4b1207809e7547146223c3814a9af586" - integrity sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw== + version "8.21.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.21.3.tgz#660b4faddb6a3e575c86e078126919961f4de4fc" + integrity sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw== y18n@^5.0.5: version "5.0.8"