Auto merge of #3481 - RalfJung:rustup, r=RalfJung

Rustup
This commit is contained in:
bors 2024-04-17 19:21:44 +00:00
commit d261b53081
62 changed files with 471 additions and 286 deletions

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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(

View File

@ -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 })

View File

@ -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))
}

View File

@ -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)?;
}

View File

@ -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())
}

View File

@ -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 => {

View File

@ -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 {

View File

@ -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:?}"

View File

@ -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();
}
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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());
}
}
}

View File

@ -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());
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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())
}
}

View File

@ -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)
}
}

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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)

View File

@ -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
}

View File

@ -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
}

View File

@ -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)]

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -1 +1 @@
803e33a4460c82581bd01d4008d0f44aef1ddfe8
c45dee5efd0c042e9d1e24559ebd0d6424d8aa70

View File

@ -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

View File

@ -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));
}
}

View File

@ -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

View File

@ -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)
}

View File

@ -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);

View File

@ -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)
}

View File

@ -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.

View File

@ -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;

View File

@ -0,0 +1 @@
// Empty

View 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);
}

View File

@ -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() {

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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();
}
}

View File

@ -148,7 +148,7 @@ mod test_foreign_items {
#![rustc_dummy]
#[rustc_dummy]
fn rust_get_test_int() -> u32;
fn rust_get_test_int() -> isize;
}
}
}

View File

@ -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() { }

View File

@ -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`.

View File

@ -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

View File

@ -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`.

View File

@ -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() {}

View File

@ -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`.

View File

@ -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;
}
}

View 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
}
}
};
}

View File

@ -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`.

View File

@ -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
}
}

View File

@ -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`.

View File

@ -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();
}

View 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() {}

View 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`.

View File

@ -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}"