mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 15:23:46 +00:00
commit
d261b53081
@ -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)
|
||||
}
|
||||
|
@ -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>,
|
||||
@ -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<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
|
||||
@ -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<CtfeProvenance>,
|
||||
_kind: Option<MemoryKind<Self::MemoryKind>>,
|
||||
) -> InterpResult<$tcx, Pointer<CtfeProvenance>> {
|
||||
Ok(ptr)
|
||||
}
|
||||
|
@ -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>> {
|
||||
@ -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> {
|
||||
@ -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(
|
||||
|
@ -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 })
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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)?;
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
}
|
||||
|
||||
|
@ -660,8 +660,14 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
}
|
||||
DefKind::Impl { of_trait } => {
|
||||
if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) {
|
||||
check_impl_items_against_trait(tcx, def_id, impl_trait_header);
|
||||
check_on_unimplemented(tcx, def_id);
|
||||
if tcx
|
||||
.ensure()
|
||||
.coherent_trait(impl_trait_header.trait_ref.instantiate_identity().def_id)
|
||||
.is_ok()
|
||||
{
|
||||
check_impl_items_against_trait(tcx, def_id, impl_trait_header);
|
||||
check_on_unimplemented(tcx, def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
DefKind::Trait => {
|
||||
|
@ -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 {
|
||||
|
@ -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:?}"
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -2846,8 +2846,30 @@ impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1277,11 +1277,11 @@ impl<T: Clone> Clone for RefCell<T> {
|
||||
|
||||
/// # 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())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -688,8 +688,8 @@ impl<T: Clone> Clone for Reverse<T> {
|
||||
}
|
||||
|
||||
#[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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<Mutex<Shared>>,
|
||||
/// }
|
||||
///
|
||||
/// 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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -95,7 +95,7 @@ impl<T> Cursor<T> {
|
||||
/// # 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<T> {
|
||||
Cursor { pos: 0, inner }
|
||||
}
|
||||
@ -132,7 +132,7 @@ impl<T> Cursor<T> {
|
||||
/// 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<T> Cursor<T> {
|
||||
/// 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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -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)
|
||||
|
@ -14,7 +14,7 @@ for example:
|
||||
./src/ci/docker/run.sh x86_64-gnu
|
||||
```
|
||||
|
||||
Images will output artifacts in an `obj` dir at the root of a repository. Note
|
||||
Images will output artifacts in an `obj/$image_name` dir at the root of a repository. Note
|
||||
that the script will overwrite the contents of this directory.
|
||||
|
||||
To match conditions in rusts CI, also set the environment variable `DEPLOY=1`, e.g.:
|
||||
@ -22,12 +22,9 @@ To match conditions in rusts CI, also set the environment variable `DEPLOY=1`, e
|
||||
DEPLOY=1 ./src/ci/docker/run.sh x86_64-gnu
|
||||
```
|
||||
|
||||
**NOTE**: Re-using the same `obj` dir with different docker images with
|
||||
the same target triple (e.g. `dist-x86_64-linux` and `dist-various-1`)
|
||||
may result in strange linker errors, due shared library versions differing between platforms.
|
||||
|
||||
If you encounter any issues when using multiple Docker images, try deleting your `obj` directory
|
||||
before running your command.
|
||||
**NOTE**: In CI, the script outputs the artifacts to the `obj` directory,
|
||||
while locally, to the `obj/$image_name` directory. This is primarily to prevent
|
||||
strange linker errors when using multiple Docker images.
|
||||
|
||||
## Filesystem layout
|
||||
|
||||
|
@ -33,7 +33,13 @@ ci_dir="`dirname $script_dir`"
|
||||
src_dir="`dirname $ci_dir`"
|
||||
root_dir="`dirname $src_dir`"
|
||||
|
||||
objdir=$root_dir/obj
|
||||
source "$ci_dir/shared.sh"
|
||||
|
||||
if isCI; then
|
||||
objdir=$root_dir/obj
|
||||
else
|
||||
objdir=$root_dir/obj/$image
|
||||
fi
|
||||
dist=$objdir/build/dist
|
||||
|
||||
|
||||
@ -41,12 +47,10 @@ if [ -d "$root_dir/.git" ]; then
|
||||
IS_GIT_SOURCE=1
|
||||
fi
|
||||
|
||||
source "$ci_dir/shared.sh"
|
||||
|
||||
CACHE_DOMAIN="${CACHE_DOMAIN:-ci-caches.rust-lang.org}"
|
||||
|
||||
if [ -f "$docker_dir/$image/Dockerfile" ]; then
|
||||
if [ "$CI" != "" ]; then
|
||||
if isCI; then
|
||||
hash_key=/tmp/.docker-hash-key.txt
|
||||
rm -f "${hash_key}"
|
||||
echo $image >> $hash_key
|
||||
@ -102,7 +106,7 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
|
||||
CACHE_IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci-cache:${cksum}
|
||||
|
||||
# On non-CI jobs, we don't do any caching.
|
||||
if [[ "$CI" == "" ]];
|
||||
if ! isCI;
|
||||
then
|
||||
retry docker build --rm -t rust-ci -f "$dockerfile" "$context"
|
||||
# On PR CI jobs, we don't have permissions to write to the registry cache,
|
||||
@ -289,7 +293,7 @@ else
|
||||
command=(/checkout/src/ci/run.sh)
|
||||
fi
|
||||
|
||||
if [ "$CI" != "" ]; then
|
||||
if isCI; then
|
||||
# Get some needed information for $BASE_COMMIT
|
||||
#
|
||||
# This command gets the last merge commit which we'll use as base to list
|
||||
@ -339,7 +343,9 @@ docker \
|
||||
rust-ci \
|
||||
"${command[@]}"
|
||||
|
||||
cat $objdir/${SUMMARY_FILE} >> "${GITHUB_STEP_SUMMARY}"
|
||||
if isCI; then
|
||||
cat $objdir/${SUMMARY_FILE} >> "${GITHUB_STEP_SUMMARY}"
|
||||
fi
|
||||
|
||||
if [ -f /.dockerenv ]; then
|
||||
rm -rf $objdir
|
||||
|
@ -1 +1 @@
|
||||
803e33a4460c82581bd01d4008d0f44aef1ddfe8
|
||||
c45dee5efd0c042e9d1e24559ebd0d6424d8aa70
|
||||
|
@ -141,7 +141,7 @@ 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 +283,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<CtfeProvenance>,
|
||||
tag: BorTag,
|
||||
kind: MemoryKind,
|
||||
) -> InterpResult<'tcx, Pointer<Provenance>> {
|
||||
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 +315,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
|
||||
|
@ -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<AllocId, BorTag>,
|
||||
root_ptr_tags: FxHashMap<AllocId, BorTag>,
|
||||
/// 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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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<CrateNum>,
|
||||
|
||||
/// Mapping extern static names to their base pointer.
|
||||
/// Mapping extern static names to their pointer.
|
||||
extern_statics: FxHashMap<Symbol, Pointer<Provenance>>,
|
||||
|
||||
/// 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<Provenance>> {
|
||||
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<Provenance>> {
|
||||
@ -1090,7 +1090,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
||||
alloc: Cow<'b, Allocation>,
|
||||
kind: Option<MemoryKind>,
|
||||
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra>>> {
|
||||
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<CtfeProvenance>,
|
||||
kind: Option<MemoryKind>,
|
||||
) -> InterpResult<'tcx, Pointer<Provenance>> {
|
||||
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.
|
||||
|
@ -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: <TAG> was created here, as the base tag for ALLOC
|
||||
help: <TAG> 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;
|
||||
|
1
tests/run-make/issue-107495-archive-permissions/foo.rs
Normal file
1
tests/run-make/issue-107495-archive-permissions/foo.rs
Normal file
@ -0,0 +1 @@
|
||||
// Empty
|
31
tests/run-make/issue-107495-archive-permissions/rmake.rs
Normal file
31
tests/run-make/issue-107495-archive-permissions/rmake.rs
Normal file
@ -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);
|
||||
}
|
@ -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() {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -148,7 +148,7 @@ mod test_foreign_items {
|
||||
#![rustc_dummy]
|
||||
|
||||
#[rustc_dummy]
|
||||
fn rust_get_test_int() -> u32;
|
||||
fn rust_get_test_int() -> isize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,8 +22,7 @@ struct MyType {
|
||||
impl MyTrait<MyType> for MyType {
|
||||
//~^ ERROR E0119
|
||||
fn get(&self) -> usize { (*self).clone() }
|
||||
//~^ ERROR incompatible type
|
||||
//~| ERROR mismatched types
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -7,23 +7,6 @@ LL | impl<T> MyTrait<T> for T {
|
||||
LL | impl MyTrait<MyType> for MyType {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType`
|
||||
|
||||
error[E0053]: method `get` has an incompatible type for trait
|
||||
--> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:24:22
|
||||
|
|
||||
LL | fn get(&self) -> usize { (*self).clone() }
|
||||
| ^^^^^
|
||||
| |
|
||||
| expected `MyType`, found `usize`
|
||||
| help: change the output type to match the trait: `MyType`
|
||||
|
|
||||
note: type in trait
|
||||
--> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:8:22
|
||||
|
|
||||
LL | fn get(&self) -> T;
|
||||
| ^
|
||||
= note: expected signature `fn(&MyType) -> MyType`
|
||||
found signature `fn(&MyType) -> usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:24:30
|
||||
|
|
||||
@ -32,7 +15,7 @@ LL | fn get(&self) -> usize { (*self).clone() }
|
||||
| |
|
||||
| expected `usize` because of return type
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0053, E0119, E0308.
|
||||
For more information about an error, try `rustc --explain E0053`.
|
||||
Some errors have detailed explanations: E0119, E0308.
|
||||
For more information about an error, try `rustc --explain E0119`.
|
||||
|
@ -9,13 +9,10 @@ struct TheType;
|
||||
|
||||
impl TheTrait<usize> for isize {}
|
||||
//~^ ERROR E0117
|
||||
//~| ERROR not all trait items implemented
|
||||
|
||||
impl TheTrait<TheType> for isize {}
|
||||
//~^ ERROR not all trait items implemented
|
||||
|
||||
impl TheTrait<isize> for TheType {}
|
||||
//~^ ERROR not all trait items implemented
|
||||
|
||||
impl !Send for Vec<isize> {} //~ ERROR E0117
|
||||
|
||||
|
@ -10,32 +10,8 @@ LL | impl TheTrait<usize> for isize {}
|
||||
|
|
||||
= note: define and implement a trait or new type instead
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `the_fn`
|
||||
--> $DIR/coherence-orphan.rs:10:1
|
||||
|
|
||||
LL | impl TheTrait<usize> for isize {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation
|
||||
|
|
||||
= help: implement the missing item: `fn the_fn(&self) { todo!() }`
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `the_fn`
|
||||
--> $DIR/coherence-orphan.rs:14:1
|
||||
|
|
||||
LL | impl TheTrait<TheType> for isize {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation
|
||||
|
|
||||
= help: implement the missing item: `fn the_fn(&self) { todo!() }`
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `the_fn`
|
||||
--> $DIR/coherence-orphan.rs:17:1
|
||||
|
|
||||
LL | impl TheTrait<isize> for TheType {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation
|
||||
|
|
||||
= help: implement the missing item: `fn the_fn(&self) { todo!() }`
|
||||
|
||||
error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
|
||||
--> $DIR/coherence-orphan.rs:20:1
|
||||
--> $DIR/coherence-orphan.rs:17:1
|
||||
|
|
||||
LL | impl !Send for Vec<isize> {}
|
||||
| ^^^^^^^^^^^^^^^----------
|
||||
@ -45,7 +21,6 @@ LL | impl !Send for Vec<isize> {}
|
||||
|
|
||||
= note: define and implement a trait or new type instead
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0046, E0117.
|
||||
For more information about an error, try `rustc --explain E0046`.
|
||||
For more information about this error, try `rustc --explain E0117`.
|
||||
|
@ -1,5 +1,4 @@
|
||||
impl Drop for u32 {} //~ ERROR E0117
|
||||
//~| ERROR the `Drop` trait may only be implemented for local structs, enums, and unions
|
||||
//~| ERROR not all trait items implemented
|
||||
|
||||
fn main() {}
|
||||
|
@ -15,15 +15,7 @@ error[E0120]: the `Drop` trait may only be implemented for local structs, enums,
|
||||
LL | impl Drop for u32 {}
|
||||
| ^^^ must be a struct, enum, or union in the current crate
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `drop`
|
||||
--> $DIR/E0117.rs:1:1
|
||||
|
|
||||
LL | impl Drop for u32 {}
|
||||
| ^^^^^^^^^^^^^^^^^ missing `drop` in implementation
|
||||
|
|
||||
= help: implement the missing item: `fn drop(&mut self) { todo!() }`
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0046, E0117, E0120.
|
||||
For more information about an error, try `rustc --explain E0046`.
|
||||
Some errors have detailed explanations: E0117, E0120.
|
||||
For more information about an error, try `rustc --explain E0117`.
|
||||
|
5
tests/ui/extern/issue-1251.rs
vendored
5
tests/ui/extern/issue-1251.rs
vendored
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
15
tests/ui/inference/dont-collect-stmts-from-parent-body.rs
Normal file
15
tests/ui/inference/dont-collect-stmts-from-parent-body.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// issue: rust-lang/rust#124022
|
||||
|
||||
struct Type<T>;
|
||||
//~^ ERROR type parameter `T` is never used
|
||||
|
||||
fn main() {
|
||||
{
|
||||
impl<T> Type<T> {
|
||||
fn new() -> Type<T> {
|
||||
Type
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -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<T>;
|
||||
| ^ 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::<T>
|
||||
| +++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0282, E0392.
|
||||
For more information about an error, try `rustc --explain E0282`.
|
@ -2,21 +2,21 @@ fn main() {}
|
||||
|
||||
impl std::ops::AddAssign for () {
|
||||
//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
|
||||
fn add_assign(&self, other: ()) -> () { //~ ERROR incompatible type
|
||||
fn add_assign(&self, other: ()) -> () {
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::AddAssign for [(); 1] {
|
||||
//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
|
||||
fn add_assign(&self, other: [(); 1]) -> [(); 1] { //~ ERROR incompatible type
|
||||
fn add_assign(&self, other: [(); 1]) -> [(); 1] {
|
||||
[()]
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::AddAssign for &[u8] {
|
||||
//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
|
||||
fn add_assign(&self, other: &[u8]) -> &[u8] { //~ ERROR incompatible type
|
||||
fn add_assign(&self, other: &[u8]) -> &[u8] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -34,43 +34,6 @@ LL | impl std::ops::AddAssign for &[u8] {
|
||||
|
|
||||
= note: define and implement a trait or new type instead
|
||||
|
||||
error[E0053]: method `add_assign` has an incompatible type for trait
|
||||
--> $DIR/issue-67535.rs:5:19
|
||||
|
|
||||
LL | fn add_assign(&self, other: ()) -> () {
|
||||
| ^^^^^
|
||||
| |
|
||||
| types differ in mutability
|
||||
| help: change the self-receiver type to match the trait: `&mut self`
|
||||
|
|
||||
= note: expected signature `fn(&mut (), ())`
|
||||
found signature `fn(&(), ())`
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
error[E0053]: method `add_assign` has an incompatible type for trait
|
||||
--> $DIR/issue-67535.rs:12:19
|
||||
|
|
||||
LL | fn add_assign(&self, other: [(); 1]) -> [(); 1] {
|
||||
| ^^^^^
|
||||
| |
|
||||
| types differ in mutability
|
||||
| help: change the self-receiver type to match the trait: `&mut self`
|
||||
|
|
||||
= note: expected signature `fn(&mut _, _)`
|
||||
found signature `fn(&_, _) -> [(); 1]`
|
||||
|
||||
error[E0053]: method `add_assign` has an incompatible type for trait
|
||||
--> $DIR/issue-67535.rs:19:19
|
||||
|
|
||||
LL | fn add_assign(&self, other: &[u8]) -> &[u8] {
|
||||
| ^^^^^
|
||||
| |
|
||||
| types differ in mutability
|
||||
| help: change the self-receiver type to match the trait: `&mut self`
|
||||
|
|
||||
= note: expected signature `fn(&mut &_, &_)`
|
||||
found signature `fn(&&_, &_) -> &[u8]`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0053, E0117.
|
||||
For more information about an error, try `rustc --explain E0053`.
|
||||
For more information about this error, try `rustc --explain E0117`.
|
||||
|
@ -256,6 +256,20 @@ fn fake_macros() -> impl std::fmt::Debug {
|
||||
}
|
||||
}
|
||||
|
||||
fn fish_fight() {
|
||||
trait Rope {
|
||||
fn _____________<U>(_: Self, _: U) where Self: Sized {}
|
||||
}
|
||||
|
||||
struct T;
|
||||
|
||||
impl Rope for T {}
|
||||
|
||||
fn tug_o_war(_: impl Fn(T, T)) {}
|
||||
|
||||
tug_o_war(<T>::_____________::<T>);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
strange();
|
||||
funny();
|
||||
@ -284,4 +298,5 @@ pub fn main() {
|
||||
infcx();
|
||||
return_already();
|
||||
fake_macros();
|
||||
fish_fight();
|
||||
}
|
||||
|
20
tests/ui/wf/conflicting-impls.rs
Normal file
20
tests/ui/wf/conflicting-impls.rs
Normal file
@ -0,0 +1,20 @@
|
||||
//@ edition: 2021
|
||||
|
||||
struct Ty;
|
||||
|
||||
impl TryFrom<Ty> for u8 {
|
||||
type Error = Ty;
|
||||
fn try_from(_: Ty) -> Result<Self, Self::Error> {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Ty> for u8 {
|
||||
//~^ ERROR conflicting implementations of trait
|
||||
type Error = Ty;
|
||||
fn try_from(_: Ty) -> Result<Self, Self::Error> {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
12
tests/ui/wf/conflicting-impls.stderr
Normal file
12
tests/ui/wf/conflicting-impls.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0119]: conflicting implementations of trait `TryFrom<Ty>` for type `u8`
|
||||
--> $DIR/conflicting-impls.rs:12:1
|
||||
|
|
||||
LL | impl TryFrom<Ty> for u8 {
|
||||
| ----------------------- first implementation here
|
||||
...
|
||||
LL | impl TryFrom<Ty> for u8 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u8`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
@ -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.<label>` getting mapped to an array of actions.
|
||||
# At the moment, the beta-nominated+T-rustdoc action fully occupies the beta-nominated slot
|
||||
# preventing others from adding more beta-nominated actions.
|
||||
[notify-zulip."beta-nominated"]
|
||||
required_labels = ["T-rustdoc"]
|
||||
zulip_stream = 266220 # #t-rustdoc
|
||||
topic = "beta-nominated: #{number}"
|
||||
# Zulip polls may not be preceded by any other text and pings & short links inside
|
||||
# the title of a poll don't get recognized. Therefore we need to send two messages.
|
||||
message_on_add = [
|
||||
"""\
|
||||
@*T-rustdoc* PR #{number} "{title}" has been nominated for beta backport.
|
||||
""",
|
||||
"""\
|
||||
/poll Approve beta backport of #{number}?
|
||||
approve
|
||||
decline
|
||||
don't know
|
||||
""",
|
||||
]
|
||||
message_on_remove = "PR #{number}'s beta-nomination has been removed."
|
||||
message_on_close = "PR #{number} has been closed. Thanks for participating!"
|
||||
message_on_reopen = "PR #{number} has been reopened. Pinging @*T-rustdoc*."
|
||||
|
||||
# FIXME: Patch triagebot to support `notify-zulip.<label>` getting mapped to an array of actions.
|
||||
# At the moment, the stable-nominated+T-rustdoc action fully occupies the stable-nominated slot
|
||||
# preventing others from adding more stable-nominated actions.
|
||||
[notify-zulip."stable-nominated"]
|
||||
required_labels = ["T-rustdoc"]
|
||||
zulip_stream = 266220 # #t-rustdoc
|
||||
topic = "stable-nominated: #{number}"
|
||||
# Zulip polls may not be preceded by any other text and pings & short links inside
|
||||
# the title of a poll don't get recognized. Therefore we need to send two messages.
|
||||
message_on_add = [
|
||||
"""\
|
||||
@*T-rustdoc* PR #{number} "{title}" has been nominated for stable backport.
|
||||
""",
|
||||
"""\
|
||||
/poll Approve stable backport of #{number}?
|
||||
approve
|
||||
decline
|
||||
don't know
|
||||
""",
|
||||
]
|
||||
message_on_remove = "PR #{number}'s stable-nomination has been removed."
|
||||
message_on_close = "PR #{number} has been closed. Thanks for participating!"
|
||||
message_on_reopen = "PR #{number} has been reopened. Pinging @*T-rustdoc*."
|
||||
|
||||
[notify-zulip."I-types-nominated"]
|
||||
zulip_stream = 326866 # #T-types/nominated
|
||||
topic = "#{number}: {title}"
|
||||
|
Loading…
Reference in New Issue
Block a user