Skip to content

Rollup of 9 pull requests #124084

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c0e913f
Document overrides of `clone_from()`
coolreader18 Mar 8, 2024
8f3d7fe
meta: notify #t-rustdoc Zulip stream on backport nominations
fmease Oct 19, 2023
8bbaeee
Don't proceed into parent bodies when collecting stmts for possible r…
compiler-errors Apr 16, 2024
20414b8
Add another expression to weird-exprs.rs
allgoewer Apr 16, 2024
b7f4332
Stabilize `const_io_structs`
slanterns Apr 17, 2024
87db7c3
Address comments
coolreader18 Apr 17, 2024
9e239bd
interpret: pass MemoryKind to adjust_alloc_base_pointer
RalfJung Apr 16, 2024
ae7b07f
interpret: rename base_pointer -> root_pointer
RalfJung Apr 16, 2024
182698f
Don't error on subtyping of equal types
oli-obk Apr 17, 2024
66a73f0
Add regression test for #107495
bjorn3 Mar 19, 2024
297fceb
Use the default file permissions when writing
bjorn3 Mar 19, 2024
6298d8f
Remove libc from rust_get_test_int uses
saethlin Apr 16, 2024
d7d1070
Rollup merge of #116957 - fmease:meta-notify-rustdoc-zulip-on-backpor…
matthiaskrgr Apr 17, 2024
21deaed
Rollup merge of #122201 - coolreader18:doc-clone_from, r=dtolnay
matthiaskrgr Apr 17, 2024
d5258af
Rollup merge of #122723 - bjorn3:archive_writer_fixes, r=nnethercote
matthiaskrgr Apr 17, 2024
6388167
Rollup merge of #124030 - RalfJung:adjust_alloc_base_pointer, r=oli-obk
matthiaskrgr Apr 17, 2024
72ff1a3
Rollup merge of #124037 - compiler-errors:dont-parent-body, r=michael…
matthiaskrgr Apr 17, 2024
8f3fd93
Rollup merge of #124049 - slanterns:const_io_structs_stabilize, r=jhp…
matthiaskrgr Apr 17, 2024
abac22f
Rollup merge of #124062 - allgoewer:fish-fight, r=oli-obk
matthiaskrgr Apr 17, 2024
116c0f7
Rollup merge of #124066 - oli-obk:define_opaque_types7, r=compiler-er…
matthiaskrgr Apr 17, 2024
abbe0d0
Rollup merge of #124073 - saethlin:rust-get-test-int, r=wesleywiser
matthiaskrgr Apr 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions compiler/rustc_codegen_ssa/src/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -280,22 +280,33 @@ 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);
// Drop src_archives to unmap all input archives, which is necessary if we want to write the
// 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)
}
Expand Down
35 changes: 21 additions & 14 deletions compiler/rustc_const_eval/src/interpret/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Self::Provenance>> {
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<Self::Provenance>>;

/// 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<Self::Provenance>>;

/// "Int-to-pointer cast"
fn ptr_from_addr_cast(
ecx: &InterpCx<'mir, 'tcx, Self>,
Expand All @@ -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.
Expand All @@ -354,6 +347,19 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
kind: Option<MemoryKind<Self::MemoryKind>>,
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>;

/// 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<MemoryKind<Self::MemoryKind>>,
) -> InterpResult<'tcx, Pointer<Self::Provenance>>;

/// Evaluate the inline assembly.
///
/// This should take care of jumping to the next block (one of `targets`) when asm goto
Expand Down Expand Up @@ -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> {
Expand All @@ -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<CtfeProvenance>,
_kind: Option<MemoryKind<Self::MemoryKind>>,
) -> InterpResult<$tcx, Pointer<CtfeProvenance>> {
Ok(ptr)
}
Expand Down
18 changes: 12 additions & 6 deletions compiler/rustc_const_eval/src/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<CtfeProvenance>,
) -> InterpResult<'tcx, Pointer<M::Provenance>> {
Expand All @@ -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<M::Provenance> {
Expand All @@ -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(
Expand Down Expand Up @@ -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(
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_const_eval/src/interpret/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -764,15 +764,15 @@ 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),
})
};
let layout = from_known_layout(self.tcx, self.param_env, layout, || self.layout_of(ty))?;
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,
))?;
Expand All @@ -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 })
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}

Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:?}"
Expand Down
26 changes: 22 additions & 4 deletions library/alloc/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2088,11 +2088,29 @@ impl<T: Clone, A: Allocator + Clone> 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();
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions library/alloc/src/collections/binary_heap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,12 @@ impl<T: Clone, A: Allocator + Clone> Clone for BinaryHeap<T, A> {
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);
}
Expand Down
4 changes: 2 additions & 2 deletions library/alloc/src/collections/btree/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ impl<T: Clone, A: Allocator + Clone> Clone for BTreeSet<T, A> {
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);
}
}

Expand Down
22 changes: 14 additions & 8 deletions library/alloc/src/collections/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2126,16 +2126,22 @@ impl<T: Clone, A: Allocator + Clone> Clone for LinkedList<T, A> {
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());
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions library/alloc/src/collections/vec_deque/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,13 @@ impl<T: Clone, A: Allocator + Clone> Clone for VecDeque<T, A> {
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());
}
}

Expand Down
4 changes: 4 additions & 0 deletions library/alloc/src/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Loading
Loading