diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index d336973d2b9c8..c99118f5156d1 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -13,7 +13,7 @@ use object::read::macho::FatArch; use tempfile::Builder as TempFileBuilder; use std::error::Error; -use std::fs::File; +use std::fs::{self, File}; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -280,12 +280,21 @@ impl<'a> ArArchiveBuilder<'a> { // This prevents programs (including rustc) from attempting to read a partial archive. // It also enables writing an archive with the same filename as a dependency on Windows as // required by a test. - let mut archive_tmpfile = TempFileBuilder::new() + // The tempfile crate currently uses 0o600 as mode for the temporary files and directories + // it creates. We need it to be the default mode for back compat reasons however. (See + // #107495) To handle this we are telling tempfile to create a temporary directory instead + // and then inside this directory create a file using File::create. + let archive_tmpdir = TempFileBuilder::new() .suffix(".temp-archive") - .tempfile_in(output.parent().unwrap_or_else(|| Path::new(""))) - .map_err(|err| io_error_context("couldn't create a temp file", err))?; + .tempdir_in(output.parent().unwrap_or_else(|| Path::new(""))) + .map_err(|err| { + io_error_context("couldn't create a directory for the temp file", err) + })?; + let archive_tmpfile_path = archive_tmpdir.path().join("tmp.a"); + let mut archive_tmpfile = File::create_new(&archive_tmpfile_path) + .map_err(|err| io_error_context("couldn't create the temp file", err))?; - write_archive_to_stream(archive_tmpfile.as_file_mut(), &entries, archive_kind, false)?; + write_archive_to_stream(&mut archive_tmpfile, &entries, archive_kind, false)?; let any_entries = !entries.is_empty(); drop(entries); @@ -293,9 +302,11 @@ impl<'a> ArArchiveBuilder<'a> { // output archive to the same location as an input archive on Windows. drop(self.src_archives); - archive_tmpfile - .persist(output) - .map_err(|err| io_error_context("failed to rename archive file", err.error))?; + fs::rename(archive_tmpfile_path, output) + .map_err(|err| io_error_context("failed to rename archive file", err))?; + archive_tmpdir + .close() + .map_err(|err| io_error_context("failed to remove temporary directory", err))?; Ok(any_entries) } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 3aeae5ebf6de6..7617cb57b3cd4 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -288,28 +288,19 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { } /// Return the `AllocId` for the given thread-local static in the current thread. - fn thread_local_static_base_pointer( + fn thread_local_static_pointer( _ecx: &mut InterpCx<'mir, 'tcx, Self>, def_id: DefId, ) -> InterpResult<'tcx, Pointer> { throw_unsup!(ThreadLocalStatic(def_id)) } - /// Return the root pointer for the given `extern static`. - fn extern_static_base_pointer( + /// Return the `AllocId` for the given `extern static`. + fn extern_static_pointer( ecx: &InterpCx<'mir, 'tcx, Self>, def_id: DefId, ) -> InterpResult<'tcx, Pointer>; - /// Return a "base" pointer for the given allocation: the one that is used for direct - /// accesses to this static/const/fn allocation, or the one returned from the heap allocator. - /// - /// Not called on `extern` or thread-local statics (those use the methods above). - fn adjust_alloc_base_pointer( - ecx: &InterpCx<'mir, 'tcx, Self>, - ptr: Pointer, - ) -> InterpResult<'tcx, Pointer>; - /// "Int-to-pointer cast" fn ptr_from_addr_cast( ecx: &InterpCx<'mir, 'tcx, Self>, @@ -336,6 +327,8 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// Called to adjust allocations to the Provenance and AllocExtra of this machine. /// + /// If `alloc` contains pointers, then they are all pointing to globals. + /// /// The way we construct allocations is to always first construct it without extra and then add /// the extra. This keeps uniform code paths for handling both allocations created by CTFE for /// globals, and allocations created by Miri during evaluation. @@ -354,6 +347,19 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { kind: Option>, ) -> InterpResult<'tcx, Cow<'b, Allocation>>; + /// Return a "root" pointer for the given allocation: the one that is used for direct + /// accesses to this static/const/fn allocation, or the one returned from the heap allocator. + /// + /// Not called on `extern` or thread-local statics (those use the methods above). + /// + /// `kind` is the kind of the allocation the pointer points to; it can be `None` when + /// it's a global and `GLOBAL_KIND` is `None`. + fn adjust_alloc_root_pointer( + ecx: &InterpCx<'mir, 'tcx, Self>, + ptr: Pointer, + kind: Option>, + ) -> InterpResult<'tcx, Pointer>; + /// Evaluate the inline assembly. /// /// This should take care of jumping to the next block (one of `targets`) when asm goto @@ -592,7 +598,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { Ok(alloc) } - fn extern_static_base_pointer( + fn extern_static_pointer( ecx: &InterpCx<$mir, $tcx, Self>, def_id: DefId, ) -> InterpResult<$tcx, Pointer> { @@ -601,9 +607,10 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { } #[inline(always)] - fn adjust_alloc_base_pointer( + fn adjust_alloc_root_pointer( _ecx: &InterpCx<$mir, $tcx, Self>, ptr: Pointer, + _kind: Option>, ) -> InterpResult<$tcx, Pointer> { Ok(ptr) } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index fbb0907f7d054..594e3b3212f2e 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -165,7 +165,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// /// This function can fail only if `ptr` points to an `extern static`. #[inline] - pub fn global_base_pointer( + pub fn global_root_pointer( &self, ptr: Pointer, ) -> InterpResult<'tcx, Pointer> { @@ -178,12 +178,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { bug!("global memory cannot point to thread-local static") } Some(GlobalAlloc::Static(def_id)) if self.tcx.is_foreign_item(def_id) => { - return M::extern_static_base_pointer(self, def_id); + return M::extern_static_pointer(self, def_id); + } + None => { + assert!( + self.memory.extra_fn_ptr_map.contains_key(&alloc_id), + "{alloc_id:?} is neither global nor a function pointer" + ); } _ => {} } // And we need to get the provenance. - M::adjust_alloc_base_pointer(self, ptr) + M::adjust_alloc_root_pointer(self, ptr, M::GLOBAL_KIND.map(MemoryKind::Machine)) } pub fn fn_ptr(&mut self, fn_val: FnVal<'tcx, M::ExtraFnVal>) -> Pointer { @@ -197,9 +203,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { id } }; - // Functions are global allocations, so make sure we get the right base pointer. + // Functions are global allocations, so make sure we get the right root pointer. // We know this is not an `extern static` so this cannot fail. - self.global_base_pointer(Pointer::from(id)).unwrap() + self.global_root_pointer(Pointer::from(id)).unwrap() } pub fn allocate_ptr( @@ -240,7 +246,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); let alloc = M::adjust_allocation(self, id, Cow::Owned(alloc), Some(kind))?; self.memory.alloc_map.insert(id, (kind, alloc.into_owned())); - M::adjust_alloc_base_pointer(self, Pointer::from(id)) + M::adjust_alloc_root_pointer(self, Pointer::from(id), Some(kind)) } pub fn reallocate_ptr( diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 842fb6d204c29..c120154ce2a70 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -764,7 +764,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Other cases need layout. let adjust_scalar = |scalar| -> InterpResult<'tcx, _> { Ok(match scalar { - Scalar::Ptr(ptr, size) => Scalar::Ptr(self.global_base_pointer(ptr)?, size), + Scalar::Ptr(ptr, size) => Scalar::Ptr(self.global_root_pointer(ptr)?, size), Scalar::Int(int) => Scalar::Int(int), }) }; @@ -772,7 +772,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let imm = match val_val { mir::ConstValue::Indirect { alloc_id, offset } => { // This is const data, no mutation allowed. - let ptr = self.global_base_pointer(Pointer::new( + let ptr = self.global_root_pointer(Pointer::new( CtfeProvenance::from(alloc_id).as_immutable(), offset, ))?; @@ -784,7 +784,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // This is const data, no mutation allowed. let alloc_id = self.tcx.reserve_and_set_memory_alloc(data); let ptr = Pointer::new(CtfeProvenance::from(alloc_id).as_immutable(), Size::ZERO); - Immediate::new_slice(self.global_base_pointer(ptr)?.into(), meta, self) + Immediate::new_slice(self.global_root_pointer(ptr)?.into(), meta, self) } }; Ok(OpTy { op: Operand::Immediate(imm), layout }) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index e32aea39fc597..1549eddabbccf 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -1010,7 +1010,7 @@ where ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { // This must be an allocation in `tcx` let _ = self.tcx.global_alloc(raw.alloc_id); - let ptr = self.global_base_pointer(Pointer::from(raw.alloc_id))?; + let ptr = self.global_root_pointer(Pointer::from(raw.alloc_id))?; let layout = self.layout_of(raw.ty)?; Ok(self.ptr_to_mplace(ptr.into(), layout)) } diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index db6c2833b9d52..c3f26da8a79b8 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -144,7 +144,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { use rustc_middle::mir::Rvalue::*; match *rvalue { ThreadLocalRef(did) => { - let ptr = M::thread_local_static_base_pointer(self, did)?; + let ptr = M::thread_local_static_pointer(self, did)?; self.write_pointer(ptr, &dest)?; } diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index a9ca268a2a96f..b603ef0d27a47 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -28,7 +28,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ensure_monomorphic_enough(*self.tcx, poly_trait_ref)?; let vtable_symbolic_allocation = self.tcx.reserve_and_set_vtable_alloc(ty, poly_trait_ref); - let vtable_ptr = self.global_base_pointer(Pointer::from(vtable_symbolic_allocation))?; + let vtable_ptr = self.global_root_pointer(Pointer::from(vtable_symbolic_allocation))?; Ok(vtable_ptr.into()) } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 4a73ce2e64095..d9e5289f6323b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2011,12 +2011,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (span, code) in errors_causecode { self.dcx().try_steal_modify_and_emit_err(span, StashKey::MaybeForgetReturn, |err| { if let Some(fn_sig) = self.body_fn_sig() - && let ExprBindingObligation(_, _, hir_id, ..) = code + && let ExprBindingObligation(_, _, binding_hir_id, ..) = code && !fn_sig.output().is_unit() { let mut block_num = 0; let mut found_semi = false; - for (_, node) in self.tcx.hir().parent_iter(hir_id) { + for (hir_id, node) in self.tcx.hir().parent_iter(binding_hir_id) { + // Don't proceed into parent bodies + if hir_id.owner != binding_hir_id.owner { + break; + } match node { hir::Node::Stmt(stmt) => { if let hir::StmtKind::Semi(expr) = stmt.kind { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 1dbf435e8c738..255e688fbc1d9 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -952,7 +952,7 @@ impl<'tcx> InferCtxt<'tcx> { // a test for it. (_, ty::Infer(ty::TyVar(_))) => {} (ty::Infer(ty::TyVar(_)), _) => {} - _ if (r_a, r_b).has_opaque_types() => { + _ if r_a != r_b && (r_a, r_b).has_opaque_types() => { span_bug!( cause.span(), "opaque types got hidden types registered from within subtype predicate: {r_a:?} vs {r_b:?}" diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index ed3ad8b39a539..e5d62447eb20e 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2088,11 +2088,29 @@ impl Clone for Box<[T], A> { self.to_vec_in(alloc).into_boxed_slice() } - fn clone_from(&mut self, other: &Self) { - if self.len() == other.len() { - self.clone_from_slice(&other); + /// Copies `source`'s contents into `self` without creating a new allocation, + /// so long as the two are of the same length. + /// + /// # Examples + /// + /// ``` + /// let x = Box::new([5, 6, 7]); + /// let mut y = Box::new([8, 9, 10]); + /// let yp: *const [i32] = &*y; + /// + /// y.clone_from(&x); + /// + /// // The value is the same + /// assert_eq!(x, y); + /// + /// // And no allocation occurred + /// assert_eq!(yp, &*y); + /// ``` + fn clone_from(&mut self, source: &Self) { + if self.len() == source.len() { + self.clone_from_slice(&source); } else { - *self = other.clone(); + *self = source.clone(); } } } diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 83b2678f7f52d..c54f0062824a1 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -385,6 +385,12 @@ impl Clone for BinaryHeap { BinaryHeap { data: self.data.clone() } } + /// Overwrites the contents of `self` with a clone of the contents of `source`. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids reallocation if possible. + /// + /// See [`Vec::clone_from()`] for more details. fn clone_from(&mut self, source: &Self) { self.data.clone_from(&source.data); } diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 7508ae468ae5b..b0bd6ef2d3c63 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -116,8 +116,8 @@ impl Clone for BTreeSet { BTreeSet { map: self.map.clone() } } - fn clone_from(&mut self, other: &Self) { - self.map.clone_from(&other.map); + fn clone_from(&mut self, source: &Self) { + self.map.clone_from(&source.map); } } diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 6dfb82ac807a0..1c90c171a155b 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -2126,16 +2126,22 @@ impl Clone for LinkedList { list } - fn clone_from(&mut self, other: &Self) { - let mut iter_other = other.iter(); - if self.len() > other.len() { - self.split_off(other.len()); + /// Overwrites the contents of `self` with a clone of the contents of `source`. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids reallocation of the nodes of the linked list. Additionally, + /// if the element type `T` overrides `clone_from()`, this will reuse the + /// resources of `self`'s elements as well. + fn clone_from(&mut self, source: &Self) { + let mut source_iter = source.iter(); + if self.len() > source.len() { + self.split_off(source.len()); } - for (elem, elem_other) in self.iter_mut().zip(&mut iter_other) { - elem.clone_from(elem_other); + for (elem, source_elem) in self.iter_mut().zip(&mut source_iter) { + elem.clone_from(source_elem); } - if !iter_other.is_empty() { - self.extend(iter_other.cloned()); + if !source_iter.is_empty() { + self.extend(source_iter.cloned()); } } } diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 693ecb0b6b48d..4643a6bbe2ecd 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -113,9 +113,13 @@ impl Clone for VecDeque { deq } - fn clone_from(&mut self, other: &Self) { + /// Overwrites the contents of `self` with a clone of the contents of `source`. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids reallocation if possible. + fn clone_from(&mut self, source: &Self) { self.clear(); - self.extend(other.iter().cloned()); + self.extend(source.iter().cloned()); } } diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 5d552c8f15c60..082af1447ece4 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2097,6 +2097,10 @@ impl Clone for String { String { vec: self.vec.clone() } } + /// Clones the contents of `source` into `self`. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids reallocation if possible. fn clone_from(&mut self, source: &Self) { self.vec.clone_from(&source.vec); } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 465da39f184b1..1930be65bfb87 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2846,8 +2846,30 @@ impl Clone for Vec { crate::slice::to_vec(&**self, alloc) } - fn clone_from(&mut self, other: &Self) { - crate::slice::SpecCloneIntoVec::clone_into(other.as_slice(), self); + /// Overwrites the contents of `self` with a clone of the contents of `source`. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids reallocation if possible. Additionally, if the element type + /// `T` overrides `clone_from()`, this will reuse the resources of `self`'s + /// elements as well. + /// + /// # Examples + /// + /// ``` + /// let x = vec![5, 6, 7]; + /// let mut y = vec![8, 9, 10]; + /// let yp: *const i32 = y.as_ptr(); + /// + /// y.clone_from(&x); + /// + /// // The value is the same + /// assert_eq!(x, y); + /// + /// // And no reallocation occurred + /// assert_eq!(yp, y.as_ptr()); + /// ``` + fn clone_from(&mut self, source: &Self) { + crate::slice::SpecCloneIntoVec::clone_into(source.as_slice(), self); } } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 58b9ba4accb61..ae0436bc5209e 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1277,11 +1277,11 @@ impl Clone for RefCell { /// # Panics /// - /// Panics if `other` is currently mutably borrowed. + /// Panics if `source` is currently mutably borrowed. #[inline] #[track_caller] - fn clone_from(&mut self, other: &Self) { - self.get_mut().clone_from(&other.borrow()) + fn clone_from(&mut self, source: &Self) { + self.get_mut().clone_from(&source.borrow()) } } diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index fa218600ed925..2fd9e17c994fe 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -688,8 +688,8 @@ impl Clone for Reverse { } #[inline] - fn clone_from(&mut self, other: &Self) { - self.0.clone_from(&other.0) + fn clone_from(&mut self, source: &Self) { + self.0.clone_from(&source.0) } } diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index fe39f6c0b5691..7691721b91e21 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -576,6 +576,42 @@ impl Clone for Waker { } } + /// Assigns a clone of `source` to `self`, unless [`self.will_wake(source)`][Waker::will_wake] anyway. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids cloning the waker if `self` is already the same waker. + /// + /// # Examples + /// + /// ``` + /// use std::future::Future; + /// use std::pin::Pin; + /// use std::sync::{Arc, Mutex}; + /// use std::task::{Context, Poll, Waker}; + /// + /// struct Waiter { + /// shared: Arc>, + /// } + /// + /// struct Shared { + /// waker: Waker, + /// // ... + /// } + /// + /// impl Future for Waiter { + /// type Output = (); + /// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + /// let mut shared = self.shared.lock().unwrap(); + /// + /// // update the waker + /// shared.waker.clone_from(cx.waker()); + /// + /// // readiness logic ... + /// # Poll::Ready(()) + /// } + /// } + /// + /// ``` #[inline] fn clone_from(&mut self, source: &Self) { if !self.will_wake(source) { diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 2cc9afe92497b..5039f0b6bb289 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -1271,8 +1271,8 @@ where } #[inline] - fn clone_from(&mut self, other: &Self) { - self.base.clone_from(&other.base); + fn clone_from(&mut self, source: &Self) { + self.base.clone_from(&source.base); } } diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 3910100f212fb..f0a498fc7bbca 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -978,6 +978,10 @@ where Self { base: self.base.clone() } } + /// Overwrites the contents of `self` with a clone of the contents of `source`. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids reallocation if possible. #[inline] fn clone_from(&mut self, other: &Self) { self.base.clone_from(&other.base); diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 8927e9a47fa83..20ebe1c4f8a06 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -606,6 +606,10 @@ impl Clone for OsString { OsString { inner: self.inner.clone() } } + /// Clones the contents of `source` into `self`. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids reallocation if possible. #[inline] fn clone_from(&mut self, source: &Self) { self.inner.clone_from(&source.inner) diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 49dde828c1fc4..5b782fff7e52e 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -95,7 +95,7 @@ impl Cursor { /// # force_inference(&buff); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] + #[rustc_const_stable(feature = "const_io_structs", since = "CURRENT_RUSTC_VERSION")] pub const fn new(inner: T) -> Cursor { Cursor { pos: 0, inner } } @@ -132,7 +132,7 @@ impl Cursor { /// let reference = buff.get_ref(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] + #[rustc_const_stable(feature = "const_io_structs", since = "CURRENT_RUSTC_VERSION")] pub const fn get_ref(&self) -> &T { &self.inner } @@ -178,7 +178,7 @@ impl Cursor { /// assert_eq!(buff.position(), 1); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] + #[rustc_const_stable(feature = "const_io_structs", since = "CURRENT_RUSTC_VERSION")] pub const fn position(&self) -> u64 { self.pos } diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index 16eaed15e720c..266a447f06b5c 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -51,7 +51,7 @@ pub struct Empty; /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] +#[rustc_const_stable(feature = "const_io_structs", since = "CURRENT_RUSTC_VERSION")] pub const fn empty() -> Empty { Empty } @@ -173,7 +173,7 @@ pub struct Repeat { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] +#[rustc_const_stable(feature = "const_io_structs", since = "CURRENT_RUSTC_VERSION")] pub const fn repeat(byte: u8) -> Repeat { Repeat { byte } } @@ -276,7 +276,7 @@ pub struct Sink; /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] +#[rustc_const_stable(feature = "const_io_structs", since = "CURRENT_RUSTC_VERSION")] pub const fn sink() -> Sink { Sink } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 72ae38cfa20ec..d152626d86a07 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -407,7 +407,6 @@ // tidy-alphabetical-start #![feature(const_collections_with_hasher)] #![feature(const_hash)] -#![feature(const_io_structs)] #![feature(const_ip)] #![feature(const_ipv4)] #![feature(const_ipv6)] diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 5f43d63bf8484..0636f55771eed 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1628,6 +1628,10 @@ impl Clone for PathBuf { PathBuf { inner: self.inner.clone() } } + /// Clones the contents of `source` into `self`. + /// + /// This method is preferred over simply assigning `source.clone()` to `self`, + /// as it avoids reallocation if possible. #[inline] fn clone_from(&mut self, source: &Self) { self.inner.clone_from(&source.inner) diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index fec39ec2b8e31..b4983656adc10 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -141,7 +141,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - fn addr_from_alloc_id(&self, alloc_id: AllocId) -> InterpResult<'tcx, u64> { + fn addr_from_alloc_id( + &self, + alloc_id: AllocId, + _kind: MemoryKind, + ) -> InterpResult<'tcx, u64> { let ecx = self.eval_context_ref(); let mut global_state = ecx.machine.alloc_addresses.borrow_mut(); let global_state = &mut *global_state; @@ -283,16 +287,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } /// Convert a relative (tcx) pointer to a Miri pointer. - fn ptr_from_rel_ptr( + fn adjust_alloc_root_pointer( &self, ptr: Pointer, tag: BorTag, + kind: MemoryKind, ) -> InterpResult<'tcx, Pointer> { let ecx = self.eval_context_ref(); let (prov, offset) = ptr.into_parts(); // offset is relative (AllocId provenance) let alloc_id = prov.alloc_id(); - let base_addr = ecx.addr_from_alloc_id(alloc_id)?; + let base_addr = ecx.addr_from_alloc_id(alloc_id, kind)?; // Add offset with the right kind of pointer-overflowing arithmetic. let dl = ecx.data_layout(); @@ -314,9 +319,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ecx.alloc_id_from_addr(addr.bytes())? }; - // This cannot fail: since we already have a pointer with that provenance, rel_ptr_to_addr + // This cannot fail: since we already have a pointer with that provenance, adjust_alloc_root_pointer // must have been called in the past, so we can just look up the address in the map. - let base_addr = ecx.addr_from_alloc_id(alloc_id).unwrap(); + let base_addr = *ecx.machine.alloc_addresses.borrow().base_addr.get(&alloc_id).unwrap(); // Wrapping "addr - base_addr" #[allow(clippy::cast_possible_wrap)] // we want to wrap here diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index f21315790a57c..24e2a9a74bbe9 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -89,10 +89,10 @@ pub struct GlobalStateInner { borrow_tracker_method: BorrowTrackerMethod, /// Next unused pointer ID (tag). next_ptr_tag: BorTag, - /// Table storing the "base" tag for each allocation. - /// The base tag is the one used for the initial pointer. + /// Table storing the "root" tag for each allocation. + /// The root tag is the one used for the initial pointer. /// We need this in a separate table to handle cyclic statics. - base_ptr_tags: FxHashMap, + root_ptr_tags: FxHashMap, /// Next unused call ID (for protectors). next_call_id: CallId, /// All currently protected tags. @@ -175,7 +175,7 @@ impl GlobalStateInner { GlobalStateInner { borrow_tracker_method, next_ptr_tag: BorTag::one(), - base_ptr_tags: FxHashMap::default(), + root_ptr_tags: FxHashMap::default(), next_call_id: NonZero::new(1).unwrap(), protected_tags: FxHashMap::default(), tracked_pointer_tags, @@ -213,8 +213,8 @@ impl GlobalStateInner { } } - pub fn base_ptr_tag(&mut self, id: AllocId, machine: &MiriMachine<'_, '_>) -> BorTag { - self.base_ptr_tags.get(&id).copied().unwrap_or_else(|| { + pub fn root_ptr_tag(&mut self, id: AllocId, machine: &MiriMachine<'_, '_>) -> BorTag { + self.root_ptr_tags.get(&id).copied().unwrap_or_else(|| { let tag = self.new_ptr(); if self.tracked_pointer_tags.contains(&tag) { machine.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag( @@ -223,14 +223,14 @@ impl GlobalStateInner { None, )); } - trace!("New allocation {:?} has base tag {:?}", id, tag); - self.base_ptr_tags.try_insert(id, tag).unwrap(); + trace!("New allocation {:?} has rpot tag {:?}", id, tag); + self.root_ptr_tags.try_insert(id, tag).unwrap(); tag }) } pub fn remove_unreachable_allocs(&mut self, allocs: &LiveAllocs<'_, '_, '_>) { - self.base_ptr_tags.retain(|id, _| allocs.is_live(*id)); + self.root_ptr_tags.retain(|id, _| allocs.is_live(*id)); } } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index aa99a14b18e62..6d4a5bd41b1eb 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -20,7 +20,7 @@ fn err_sb_ub<'tcx>( #[derive(Clone, Debug)] pub struct AllocHistory { id: AllocId, - base: (Item, Span), + root: (Item, Span), creations: smallvec::SmallVec<[Creation; 1]>, invalidations: smallvec::SmallVec<[Invalidation; 1]>, protectors: smallvec::SmallVec<[Protection; 1]>, @@ -225,7 +225,7 @@ impl AllocHistory { pub fn new(id: AllocId, item: Item, machine: &MiriMachine<'_, '_>) -> Self { Self { id, - base: (item, machine.current_span()), + root: (item, machine.current_span()), creations: SmallVec::new(), invalidations: SmallVec::new(), protectors: SmallVec::new(), @@ -342,15 +342,15 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> { }) }) .or_else(|| { - // If we didn't find a retag that created this tag, it might be the base tag of + // If we didn't find a retag that created this tag, it might be the root tag of // this allocation. - if self.history.base.0.tag() == tag { + if self.history.root.0.tag() == tag { Some(( format!( - "{tag:?} was created here, as the base tag for {:?}", + "{tag:?} was created here, as the root tag for {:?}", self.history.id ), - self.history.base.1.data(), + self.history.root.1.data(), )) } else { None diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index b4005515d9d90..a6dd1d829cb4f 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -518,9 +518,9 @@ impl Stacks { // not through a pointer). That is, whenever we directly write to a local, this will pop // everything else off the stack, invalidating all previous pointers, // and in particular, *all* raw pointers. - MemoryKind::Stack => (state.base_ptr_tag(id, machine), Permission::Unique), + MemoryKind::Stack => (state.root_ptr_tag(id, machine), Permission::Unique), // Everything else is shared by default. - _ => (state.base_ptr_tag(id, machine), Permission::SharedReadWrite), + _ => (state.root_ptr_tag(id, machine), Permission::SharedReadWrite), }; Stacks::new(size, perm, base_tag, id, machine) } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs index 76430498e2bf0..bebd14d2f1e71 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs @@ -47,7 +47,7 @@ impl Stack { let mut first_removed = None; // We never consider removing the bottom-most tag. For stacks without an unknown - // bottom this preserves the base tag. + // bottom this preserves the root tag. // Note that the algorithm below is based on considering the tag at read_idx - 1, // so precisely considering the tag at index 0 for removal when we have an unknown // bottom would complicate the implementation. The simplification of not considering @@ -93,7 +93,7 @@ impl Stack { self.unique_range = 0..self.len(); } - // Replace any Items which have been collected with the base item, a known-good value. + // Replace any Items which have been collected with the root item, a known-good value. for i in 0..CACHE_LEN { if self.cache.idx[i] >= first_removed { self.cache.items[i] = self.borrows[0]; @@ -331,7 +331,7 @@ impl<'tcx> Stack { self.verify_cache_consistency(); } - /// Construct a new `Stack` using the passed `Item` as the base tag. + /// Construct a new `Stack` using the passed `Item` as the root tag. pub fn new(item: Item) -> Self { Stack { borrows: vec![item], @@ -438,8 +438,8 @@ impl<'tcx> Stack { let mut removed = 0; let mut cursor = 0; // Remove invalid entries from the cache by rotating them to the end of the cache, then - // keep track of how many invalid elements there are and overwrite them with the base tag. - // The base tag here serves as a harmless default value. + // keep track of how many invalid elements there are and overwrite them with the root tag. + // The root tag here serves as a harmless default value. for _ in 0..CACHE_LEN - 1 { if self.cache.idx[cursor] >= start { self.cache.idx[cursor..CACHE_LEN - removed].rotate_left(1); diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 492e324de4543..fc5eb942a27b5 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -37,7 +37,7 @@ impl<'tcx> Tree { _kind: MemoryKind, machine: &MiriMachine<'_, 'tcx>, ) -> Self { - let tag = state.base_ptr_tag(id, machine); // Fresh tag for the root + let tag = state.root_ptr_tag(id, machine); // Fresh tag for the root let span = machine.current_span(); Tree::new(tag, size, span) } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 1d06d5c69d36d..0bfc59e67db19 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -503,7 +503,7 @@ pub struct MiriMachine<'mir, 'tcx> { /// Crates which are considered local for the purposes of error reporting. pub(crate) local_crates: Vec, - /// Mapping extern static names to their base pointer. + /// Mapping extern static names to their pointer. extern_statics: FxHashMap>, /// The random number generator used for resolving non-determinism. @@ -1042,14 +1042,14 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx.generate_nan(inputs) } - fn thread_local_static_base_pointer( + fn thread_local_static_pointer( ecx: &mut MiriInterpCx<'mir, 'tcx>, def_id: DefId, ) -> InterpResult<'tcx, Pointer> { ecx.get_or_create_thread_local_alloc(def_id) } - fn extern_static_base_pointer( + fn extern_static_pointer( ecx: &MiriInterpCx<'mir, 'tcx>, def_id: DefId, ) -> InterpResult<'tcx, Pointer> { @@ -1090,7 +1090,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { alloc: Cow<'b, Allocation>, kind: Option, ) -> InterpResult<'tcx, Cow<'b, Allocation>> { - let kind = kind.expect("we set our STATIC_KIND so this cannot be None"); + let kind = kind.expect("we set our GLOBAL_KIND so this cannot be None"); if ecx.machine.tracked_alloc_ids.contains(&id) { ecx.emit_diagnostic(NonHaltingDiagnostic::CreatedAlloc( id, @@ -1135,7 +1135,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { weak_memory: buffer_alloc, backtrace, }, - |ptr| ecx.global_base_pointer(ptr), + |ptr| ecx.global_root_pointer(ptr), )?; if matches!(kind, MemoryKind::Machine(kind) if kind.should_save_allocation_span()) { @@ -1148,31 +1148,33 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { Ok(Cow::Owned(alloc)) } - fn adjust_alloc_base_pointer( + fn adjust_alloc_root_pointer( ecx: &MiriInterpCx<'mir, 'tcx>, ptr: Pointer, + kind: Option, ) -> InterpResult<'tcx, Pointer> { + let kind = kind.expect("we set our GLOBAL_KIND so this cannot be None"); let alloc_id = ptr.provenance.alloc_id(); if cfg!(debug_assertions) { // The machine promises to never call us on thread-local or extern statics. match ecx.tcx.try_get_global_alloc(alloc_id) { Some(GlobalAlloc::Static(def_id)) if ecx.tcx.is_thread_local_static(def_id) => { - panic!("adjust_alloc_base_pointer called on thread-local static") + panic!("adjust_alloc_root_pointer called on thread-local static") } Some(GlobalAlloc::Static(def_id)) if ecx.tcx.is_foreign_item(def_id) => { - panic!("adjust_alloc_base_pointer called on extern static") + panic!("adjust_alloc_root_pointer called on extern static") } _ => {} } } // FIXME: can we somehow preserve the immutability of `ptr`? let tag = if let Some(borrow_tracker) = &ecx.machine.borrow_tracker { - borrow_tracker.borrow_mut().base_ptr_tag(alloc_id, &ecx.machine) + borrow_tracker.borrow_mut().root_ptr_tag(alloc_id, &ecx.machine) } else { // Value does not matter, SB is disabled BorTag::default() }; - ecx.ptr_from_rel_ptr(ptr, tag) + ecx.adjust_alloc_root_pointer(ptr, tag, kind) } /// Called on `usize as ptr` casts. diff --git a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr index f6eeef33e9ee9..8426f56004bee 100644 --- a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr @@ -6,7 +6,7 @@ LL | unsafe { *x = 0 }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created here, as the base tag for ALLOC +help: was created here, as the root tag for ALLOC --> $DIR/invalidate_against_protector3.rs:LL:CC | LL | let ptr = alloc(Layout::for_value(&0i32)) as *mut i32; diff --git a/tests/run-make/issue-107495-archive-permissions/foo.rs b/tests/run-make/issue-107495-archive-permissions/foo.rs new file mode 100644 index 0000000000000..d15abba59766b --- /dev/null +++ b/tests/run-make/issue-107495-archive-permissions/foo.rs @@ -0,0 +1 @@ +// Empty diff --git a/tests/run-make/issue-107495-archive-permissions/rmake.rs b/tests/run-make/issue-107495-archive-permissions/rmake.rs new file mode 100644 index 0000000000000..40deabe15b73c --- /dev/null +++ b/tests/run-make/issue-107495-archive-permissions/rmake.rs @@ -0,0 +1,31 @@ +#![feature(rustc_private)] + +#[cfg(unix)] +extern crate libc; +extern crate run_make_support; + +use run_make_support::{aux_build, tmp_dir}; +use std::fs; +#[cfg(unix)] +use std::os::unix::fs::PermissionsExt; +use std::path::Path; + +fn main() { + #[cfg(unix)] + unsafe { + libc::umask(0o002); + } + + aux_build().arg("foo.rs").run(); + verify(&tmp_dir().join("libfoo.rlib")); +} + +fn verify(path: &Path) { + let perm = fs::metadata(path).unwrap().permissions(); + + assert!(!perm.readonly()); + + // Check that the file is readable for everyone + #[cfg(unix)] + assert_eq!(perm.mode(), 0o100664); +} diff --git a/tests/ui/abi/anon-extern-mod.rs b/tests/ui/abi/anon-extern-mod.rs index a424f93f637c9..bb3739bc4afab 100644 --- a/tests/ui/abi/anon-extern-mod.rs +++ b/tests/ui/abi/anon-extern-mod.rs @@ -1,13 +1,9 @@ //@ run-pass //@ pretty-expanded FIXME #23616 -#![feature(rustc_private)] - -extern crate libc; - #[link(name = "rust_test_helpers", kind = "static")] extern "C" { - fn rust_get_test_int() -> libc::intptr_t; + fn rust_get_test_int() -> isize; } pub fn main() { diff --git a/tests/ui/abi/c-stack-as-value.rs b/tests/ui/abi/c-stack-as-value.rs index 6ea2051b05b3e..401bc132b6e77 100644 --- a/tests/ui/abi/c-stack-as-value.rs +++ b/tests/ui/abi/c-stack-as-value.rs @@ -1,14 +1,10 @@ //@ run-pass //@ pretty-expanded FIXME #23616 -#![feature(rustc_private)] - mod rustrt { - extern crate libc; - #[link(name = "rust_test_helpers", kind = "static")] extern "C" { - pub fn rust_get_test_int() -> libc::intptr_t; + pub fn rust_get_test_int() -> isize; } } diff --git a/tests/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs b/tests/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs index 5cbf8093c5c3c..559c40546a8a5 100644 --- a/tests/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs +++ b/tests/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs @@ -1,9 +1,6 @@ #![crate_name = "anonexternmod"] -#![feature(rustc_private)] - -extern crate libc; #[link(name = "rust_test_helpers", kind = "static")] extern "C" { - pub fn rust_get_test_int() -> libc::intptr_t; + pub fn rust_get_test_int() -> isize; } diff --git a/tests/ui/abi/foreign/auxiliary/foreign_lib.rs b/tests/ui/abi/foreign/auxiliary/foreign_lib.rs index 3c649b778bd1a..74a95b96e9fc4 100644 --- a/tests/ui/abi/foreign/auxiliary/foreign_lib.rs +++ b/tests/ui/abi/foreign/auxiliary/foreign_lib.rs @@ -1,28 +1,28 @@ #![crate_name = "foreign_lib"] -#![feature(rustc_private)] pub mod rustrt { - extern crate libc; - #[link(name = "rust_test_helpers", kind = "static")] extern "C" { - pub fn rust_get_test_int() -> libc::intptr_t; + pub fn rust_get_test_int() -> isize; } } pub mod rustrt2 { - extern crate libc; - extern "C" { - pub fn rust_get_test_int() -> libc::intptr_t; + pub fn rust_get_test_int() -> isize; } } pub mod rustrt3 { - // Different type, but same ABI (on all supported platforms). - // Ensures that we don't ICE or trigger LLVM asserts when - // importing the same symbol under different types. - // See https://github.com/rust-lang/rust/issues/32740. + // The point of this test is to ensure that we don't ICE or trigger LLVM asserts when importing + // the same symbol with different types. This is not really possible to test portably; there is + // no different signature we can come up with that is different to LLVM but which for sure has + // the same behavior on all platforms. The signed-ness of integers is ignored by LLVM as well + // as pointee types. So the only ways to make our signatures differ are to use + // differently-sized integers which is definitely an ABI mismatch, or to rely on pointers and + // isize/usize having the same ABI, which is wrong on CHERI and probably other niche platforms. + // If this test causes you trouble, please file an issue. + // See https://github.com/rust-lang/rust/issues/32740 for the bug that prompted this test. extern "C" { pub fn rust_get_test_int() -> *const u8; } @@ -32,6 +32,6 @@ pub fn local_uses() { unsafe { let x = rustrt::rust_get_test_int(); assert_eq!(x, rustrt2::rust_get_test_int()); - assert_eq!(x as *const _, rustrt3::rust_get_test_int()); + assert_eq!(x as *const u8, rustrt3::rust_get_test_int()); } } diff --git a/tests/ui/abi/foreign/foreign-dupe.rs b/tests/ui/abi/foreign/foreign-dupe.rs index 1b6df0892c70f..3473d436cb483 100644 --- a/tests/ui/abi/foreign/foreign-dupe.rs +++ b/tests/ui/abi/foreign/foreign-dupe.rs @@ -4,13 +4,12 @@ // Check that we can still call duplicated extern (imported) functions // which were declared in another crate. See issues #32740 and #32783. - extern crate foreign_lib; pub fn main() { unsafe { let x = foreign_lib::rustrt::rust_get_test_int(); assert_eq!(x, foreign_lib::rustrt2::rust_get_test_int()); - assert_eq!(x as *const _, foreign_lib::rustrt3::rust_get_test_int()); + assert_eq!(x as *const u8, foreign_lib::rustrt3::rust_get_test_int()); } } diff --git a/tests/ui/abi/foreign/foreign-no-abi.rs b/tests/ui/abi/foreign/foreign-no-abi.rs deleted file mode 100644 index 4ac47df29a710..0000000000000 --- a/tests/ui/abi/foreign/foreign-no-abi.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ run-pass -// ABI is cdecl by default - -//@ pretty-expanded FIXME #23616 - -#![feature(rustc_private)] - -mod rustrt { - extern crate libc; - - #[link(name = "rust_test_helpers", kind = "static")] - extern "C" { - pub fn rust_get_test_int() -> libc::intptr_t; - } -} - -pub fn main() { - unsafe { - rustrt::rust_get_test_int(); - } -} diff --git a/tests/ui/attributes/item-attributes.rs b/tests/ui/attributes/item-attributes.rs index 7fe7fdd97584e..daab1bccb2c4d 100644 --- a/tests/ui/attributes/item-attributes.rs +++ b/tests/ui/attributes/item-attributes.rs @@ -148,7 +148,7 @@ mod test_foreign_items { #![rustc_dummy] #[rustc_dummy] - fn rust_get_test_int() -> u32; + fn rust_get_test_int() -> isize; } } } diff --git a/tests/ui/extern/issue-1251.rs b/tests/ui/extern/issue-1251.rs index da2b8be7bc1f3..5581bddaddc16 100644 --- a/tests/ui/extern/issue-1251.rs +++ b/tests/ui/extern/issue-1251.rs @@ -2,13 +2,10 @@ #![allow(unused_attributes)] #![allow(dead_code)] //@ pretty-expanded FIXME #23616 -#![feature(rustc_private)] mod rustrt { - extern crate libc; - extern "C" { - pub fn rust_get_test_int() -> libc::intptr_t; + pub fn rust_get_test_int() -> isize; } } diff --git a/tests/ui/inference/dont-collect-stmts-from-parent-body.rs b/tests/ui/inference/dont-collect-stmts-from-parent-body.rs new file mode 100644 index 0000000000000..635fe74b8679d --- /dev/null +++ b/tests/ui/inference/dont-collect-stmts-from-parent-body.rs @@ -0,0 +1,15 @@ +// issue: rust-lang/rust#124022 + +struct Type; +//~^ ERROR type parameter `T` is never used + +fn main() { + { + impl Type { + fn new() -> Type { + Type + //~^ ERROR type annotations needed + } + } + }; +} diff --git a/tests/ui/inference/dont-collect-stmts-from-parent-body.stderr b/tests/ui/inference/dont-collect-stmts-from-parent-body.stderr new file mode 100644 index 0000000000000..f82527273fbee --- /dev/null +++ b/tests/ui/inference/dont-collect-stmts-from-parent-body.stderr @@ -0,0 +1,24 @@ +error[E0392]: type parameter `T` is never used + --> $DIR/dont-collect-stmts-from-parent-body.rs:3:13 + | +LL | struct Type; + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0282]: type annotations needed + --> $DIR/dont-collect-stmts-from-parent-body.rs:10:17 + | +LL | Type + | ^^^^ cannot infer type of the type parameter `T` declared on the struct `Type` + | +help: consider specifying the generic argument + | +LL | Type:: + | +++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0392. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/weird-exprs.rs b/tests/ui/weird-exprs.rs index d856b06e260b8..0009ed0e34c89 100644 --- a/tests/ui/weird-exprs.rs +++ b/tests/ui/weird-exprs.rs @@ -256,6 +256,20 @@ fn fake_macros() -> impl std::fmt::Debug { } } +fn fish_fight() { + trait Rope { + fn _____________(_: Self, _: U) where Self: Sized {} + } + + struct T; + + impl Rope for T {} + + fn tug_o_war(_: impl Fn(T, T)) {} + + tug_o_war(::_____________::); +} + pub fn main() { strange(); funny(); @@ -284,4 +298,5 @@ pub fn main() { infcx(); return_already(); fake_macros(); + fish_fight(); } diff --git a/triagebot.toml b/triagebot.toml index 731642ca74cbe..66b8f44d68898 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -417,6 +417,54 @@ message_on_remove = "Issue #{number}'s prioritization request has been removed." message_on_close = "Issue #{number} has been closed while requested for prioritization." message_on_reopen = "Issue #{number} has been reopened." +# FIXME: Patch triagebot to support `notify-zulip.