Auto merge of #143667 - tgross35:rollup-yqitltm, r=tgross35

Rollup of 9 pull requests

Successful merges:

 - rust-lang/rust#142357 (Simplify LLVM bitcode linker in bootstrap and add tests for it)
 - rust-lang/rust#143177 (Remove false label when `self` resolve failure does not relate to macro)
 - rust-lang/rust#143339 (Respect endianness correctly in CheckEnums test suite)
 - rust-lang/rust#143426 (clippy fix: indentation)
 - rust-lang/rust#143475 (tests: Use `cfg_target_has_reliable_f16_f128` in `conv-bits-runtime-const`)
 - rust-lang/rust#143499 (Don't call `predicates_of` on a dummy obligation cause's body id)
 - rust-lang/rust#143520 (Fix perf regression caused by tracing)
 - rust-lang/rust#143532 (More carefully consider span context when suggesting remove `&mut`)
 - rust-lang/rust#143606 (configure.py: Write last key in each section)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-07-09 06:43:41 +00:00
commit 558d25371f
48 changed files with 347 additions and 169 deletions

View file

@ -96,7 +96,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// This inherent method takes priority over the trait method with the same name in LayoutOf,
/// and allows wrapping the actual [LayoutOf::layout_of] with a tracing span.
/// See [LayoutOf::layout_of] for the original documentation.
#[inline]
#[inline(always)]
pub fn layout_of(
&self,
ty: Ty<'tcx>,

View file

@ -18,8 +18,8 @@ use rustc_target::callconv::FnAbi;
use super::{
AllocBytes, AllocId, AllocKind, AllocRange, Allocation, CTFE_ALLOC_SALT, ConstAllocation,
CtfeProvenance, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, MemoryKind,
Misalignment, OpTy, PlaceTy, Pointer, Provenance, RangeSet, interp_ok, throw_unsup,
CtfeProvenance, EnteredTraceSpan, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy,
MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, RangeSet, interp_ok, throw_unsup,
};
/// Data returned by [`Machine::after_stack_pop`], and consumed by
@ -147,12 +147,6 @@ pub trait Machine<'tcx>: Sized {
/// already been checked before.
const ALL_CONSTS_ARE_PRECHECKED: bool = true;
/// Determines whether rustc_const_eval functions that make use of the [Machine] should make
/// tracing calls (to the `tracing` library). By default this is `false`, meaning the tracing
/// calls will supposedly be optimized out. This flag is set to `true` inside Miri, to allow
/// tracing the interpretation steps, among other things.
const TRACING_ENABLED: bool = false;
/// Whether memory accesses should be alignment-checked.
fn enforce_alignment(ecx: &InterpCx<'tcx, Self>) -> bool;
@ -634,6 +628,17 @@ pub trait Machine<'tcx>: Sized {
/// Compute the value passed to the constructors of the `AllocBytes` type for
/// abstract machine allocations.
fn get_default_alloc_params(&self) -> <Self::Bytes as AllocBytes>::AllocParams;
/// Allows enabling/disabling tracing calls from within `rustc_const_eval` at compile time, by
/// delegating the entering of [tracing::Span]s to implementors of the [Machine] trait. The
/// default implementation corresponds to tracing being disabled, meaning the tracing calls will
/// supposedly be optimized out completely. To enable tracing, override this trait method and
/// return `span.entered()`. Also see [crate::enter_trace_span].
#[must_use]
#[inline(always)]
fn enter_trace_span(_span: impl FnOnce() -> tracing::Span) -> impl EnteredTraceSpan {
()
}
}
/// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines

View file

@ -37,6 +37,7 @@ pub use self::place::{MPlaceTy, MemPlaceMeta, PlaceTy, Writeable};
use self::place::{MemPlace, Place};
pub use self::projection::{OffsetMode, Projectable};
pub use self::stack::{Frame, FrameInfo, LocalState, ReturnContinuation, StackPopInfo};
pub use self::util::EnteredTraceSpan;
pub(crate) use self::util::create_static_alloc;
pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking};
pub use self::visitor::ValueVisitor;

View file

@ -46,21 +46,20 @@ pub(crate) fn create_static_alloc<'tcx>(
interp_ok(ecx.ptr_to_mplace(Pointer::from(alloc_id).into(), layout))
}
/// This struct is needed to enforce `#[must_use]` on [tracing::span::EnteredSpan]
/// while wrapping them in an `Option`.
#[must_use]
pub enum MaybeEnteredSpan {
Some(tracing::span::EnteredSpan),
None,
}
/// A marker trait returned by [crate::interpret::Machine::enter_trace_span], identifying either a
/// real [tracing::span::EnteredSpan] in case tracing is enabled, or the dummy type `()` when
/// tracing is disabled.
pub trait EnteredTraceSpan {}
impl EnteredTraceSpan for () {}
impl EnteredTraceSpan for tracing::span::EnteredSpan {}
/// Shortand for calling [crate::interpret::Machine::enter_trace_span] on a [tracing::info_span].
/// This is supposed to be compiled out when [crate::interpret::Machine::enter_trace_span] has the
/// default implementation (i.e. when it does not actually enter the span but instead returns `()`).
/// Note: the result of this macro **must be used** because the span is exited when it's dropped.
#[macro_export]
macro_rules! enter_trace_span {
($machine:ident, $($tt:tt)*) => {
if $machine::TRACING_ENABLED {
$crate::interpret::util::MaybeEnteredSpan::Some(tracing::info_span!($($tt)*).entered())
} else {
$crate::interpret::util::MaybeEnteredSpan::None
}
$machine::enter_trace_span(|| tracing::info_span!($($tt)*))
}
}

View file

@ -1183,15 +1183,23 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
_ => "`self` value is a keyword only available in methods with a `self` parameter",
},
);
// using `let self` is wrong even if we're not in an associated method or if we're in a macro expansion.
// So, we should return early if we're in a pattern, see issue #143134.
if matches!(source, PathSource::Pat) {
return true;
}
let is_assoc_fn = self.self_type_is_available();
let self_from_macro = "a `self` parameter, but a macro invocation can only \
access identifiers it receives from parameters";
if let Some((fn_kind, span)) = &self.diag_metadata.current_function {
if let Some((fn_kind, fn_span)) = &self.diag_metadata.current_function {
// The current function has a `self` parameter, but we were unable to resolve
// a reference to `self`. This can only happen if the `self` identifier we
// are resolving came from a different hygiene context.
// are resolving came from a different hygiene context or a variable binding.
// But variable binding error is returned early above.
if fn_kind.decl().inputs.get(0).is_some_and(|p| p.is_self()) {
err.span_label(*span, format!("this function has {self_from_macro}"));
err.span_label(*fn_span, format!("this function has {self_from_macro}"));
} else {
let doesnt = if is_assoc_fn {
let (span, sugg) = fn_kind
@ -1204,7 +1212,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
// This avoids placing the suggestion into the visibility specifier.
let span = fn_kind
.ident()
.map_or(*span, |ident| span.with_lo(ident.span.hi()));
.map_or(*fn_span, |ident| fn_span.with_lo(ident.span.hi()));
(
self.r
.tcx

View file

@ -4,7 +4,7 @@ use rustc_errors::{Applicability, Diag, E0283, E0284, E0790, MultiSpan, struct_s
use rustc_hir as hir;
use rustc_hir::LangItem;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
use rustc_hir::intravisit::Visitor as _;
use rustc_infer::infer::{BoundRegionConversionTime, InferCtxt};
use rustc_infer::traits::util::elaborate;
@ -128,19 +128,26 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>(
},
);
let predicates =
tcx.predicates_of(obligation.cause.body_id.to_def_id()).instantiate_identity(tcx);
for (pred, span) in elaborate(tcx, predicates.into_iter()) {
let kind = pred.kind();
if let ty::ClauseKind::Trait(trait_pred) = kind.skip_binder()
&& param_env_candidate_may_apply(kind.rebind(trait_pred))
{
if kind.rebind(trait_pred.trait_ref)
== ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_pred.def_id()))
// If our `body_id` has been set (and isn't just from a dummy obligation cause),
// then try to look for a param-env clause that would apply. The way we compute
// this is somewhat manual, since we need the spans, so we elaborate this directly
// from `predicates_of` rather than actually looking at the param-env which
// otherwise would be more appropriate.
let body_id = obligation.cause.body_id;
if body_id != CRATE_DEF_ID {
let predicates = tcx.predicates_of(body_id.to_def_id()).instantiate_identity(tcx);
for (pred, span) in elaborate(tcx, predicates.into_iter()) {
let kind = pred.kind();
if let ty::ClauseKind::Trait(trait_pred) = kind.skip_binder()
&& param_env_candidate_may_apply(kind.rebind(trait_pred))
{
ambiguities.push(CandidateSource::ParamEnv(tcx.def_span(trait_pred.def_id())))
} else {
ambiguities.push(CandidateSource::ParamEnv(span))
if kind.rebind(trait_pred.trait_ref)
== ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_pred.def_id()))
{
ambiguities.push(CandidateSource::ParamEnv(tcx.def_span(trait_pred.def_id())))
} else {
ambiguities.push(CandidateSource::ParamEnv(span))
}
}
}
}

View file

@ -1581,12 +1581,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
'outer: loop {
while let hir::ExprKind::AddrOf(_, _, borrowed) = expr.kind {
count += 1;
let span = if expr.span.eq_ctxt(borrowed.span) {
expr.span.until(borrowed.span)
} else {
expr.span.with_hi(expr.span.lo() + BytePos(1))
};
let span =
if let Some(borrowed_span) = borrowed.span.find_ancestor_inside(expr.span) {
expr.span.until(borrowed_span)
} else {
break 'outer;
};
// Double check that the span we extracted actually corresponds to a borrow,
// rather than some macro garbage.
match self.tcx.sess.source_map().span_to_snippet(span) {
Ok(snippet) if snippet.starts_with("&") => {}
_ => break 'outer,

View file

@ -61,8 +61,8 @@ impl Layout {
/// * `align` must be a power of two,
///
/// * `size`, when rounded up to the nearest multiple of `align`,
/// must not overflow `isize` (i.e., the rounded value must be
/// less than or equal to `isize::MAX`).
/// must not overflow `isize` (i.e., the rounded value must be
/// less than or equal to `isize::MAX`).
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
#[inline]

View file

@ -1940,21 +1940,21 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
/// The precise Rust aliasing rules are somewhat in flux, but the main points are not contentious:
///
/// - If you create a safe reference with lifetime `'a` (either a `&T` or `&mut T` reference), then
/// you must not access the data in any way that contradicts that reference for the remainder of
/// `'a`. For example, this means that if you take the `*mut T` from an `UnsafeCell<T>` and cast it
/// to an `&T`, then the data in `T` must remain immutable (modulo any `UnsafeCell` data found
/// within `T`, of course) until that reference's lifetime expires. Similarly, if you create a `&mut
/// T` reference that is released to safe code, then you must not access the data within the
/// `UnsafeCell` until that reference expires.
/// you must not access the data in any way that contradicts that reference for the remainder of
/// `'a`. For example, this means that if you take the `*mut T` from an `UnsafeCell<T>` and cast it
/// to an `&T`, then the data in `T` must remain immutable (modulo any `UnsafeCell` data found
/// within `T`, of course) until that reference's lifetime expires. Similarly, if you create a
/// `&mut T` reference that is released to safe code, then you must not access the data within the
/// `UnsafeCell` until that reference expires.
///
/// - For both `&T` without `UnsafeCell<_>` and `&mut T`, you must also not deallocate the data
/// until the reference expires. As a special exception, given an `&T`, any part of it that is
/// inside an `UnsafeCell<_>` may be deallocated during the lifetime of the reference, after the
/// last time the reference is used (dereferenced or reborrowed). Since you cannot deallocate a part
/// of what a reference points to, this means the memory an `&T` points to can be deallocated only if
/// *every part of it* (including padding) is inside an `UnsafeCell`.
/// until the reference expires. As a special exception, given an `&T`, any part of it that is
/// inside an `UnsafeCell<_>` may be deallocated during the lifetime of the reference, after the
/// last time the reference is used (dereferenced or reborrowed). Since you cannot deallocate a part
/// of what a reference points to, this means the memory an `&T` points to can be deallocated only if
/// *every part of it* (including padding) is inside an `UnsafeCell`.
///
/// However, whenever a `&UnsafeCell<T>` is constructed or dereferenced, it must still point to
/// However, whenever a `&UnsafeCell<T>` is constructed or dereferenced, it must still point to
/// live memory and the compiler is allowed to insert spurious reads if it can prove that this
/// memory has not yet been deallocated.
///
@ -1962,10 +1962,10 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
/// for single-threaded code:
///
/// 1. A `&T` reference can be released to safe code and there it can co-exist with other `&T`
/// references, but not with a `&mut T`
/// references, but not with a `&mut T`
///
/// 2. A `&mut T` reference may be released to safe code provided neither other `&mut T` nor `&T`
/// co-exist with it. A `&mut T` must always be unique.
/// co-exist with it. A `&mut T` must always be unique.
///
/// Note that whilst mutating the contents of an `&UnsafeCell<T>` (even while other
/// `&UnsafeCell<T>` references alias the cell) is

View file

@ -447,28 +447,28 @@ where
/// separated by API boundaries:
///
/// * Consumer - the consumer requests objects using a Request instance; eg a crate that offers
/// fancy `Error`/`Result` reporting to users wants to request a Backtrace from a given `dyn Error`.
/// fancy `Error`/`Result` reporting to users wants to request a Backtrace from a given `dyn Error`.
///
/// * Producer - the producer provides objects when requested via Request; eg. a library with an
/// an `Error` implementation that automatically captures backtraces at the time instances are
/// created.
/// an `Error` implementation that automatically captures backtraces at the time instances are
/// created.
///
/// The consumer only needs to know where to submit their request and are expected to handle the
/// request not being fulfilled by the use of `Option<T>` in the responses offered by the producer.
///
/// * A Producer initializes the value of one of its fields of a specific type. (or is otherwise
/// prepared to generate a value requested). eg, `backtrace::Backtrace` or
/// `std::backtrace::Backtrace`
/// prepared to generate a value requested). eg, `backtrace::Backtrace` or
/// `std::backtrace::Backtrace`
/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace`). In the
/// case of a `dyn Error` trait object (the Producer), there are functions called `request_ref` and
/// `request_value` to simplify obtaining an `Option<T>` for a given type.
/// case of a `dyn Error` trait object (the Producer), there are functions called `request_ref` and
/// `request_value` to simplify obtaining an `Option<T>` for a given type.
/// * The Producer, when requested, populates the given Request object which is given as a mutable
/// reference.
/// reference.
/// * The Consumer extracts a value or reference to the requested type from the `Request` object
/// wrapped in an `Option<T>`; in the case of `dyn Error` the aforementioned `request_ref` and `
/// request_value` methods mean that `dyn Error` users don't have to deal with the `Request` type at
/// all (but `Error` implementors do). The `None` case of the `Option` suggests only that the
/// Producer cannot currently offer an instance of the requested type, not it can't or never will.
/// wrapped in an `Option<T>`; in the case of `dyn Error` the aforementioned `request_ref` and `
/// request_value` methods mean that `dyn Error` users don't have to deal with the `Request` type at
/// all (but `Error` implementors do). The `None` case of the `Option` suggests only that the
/// Producer cannot currently offer an instance of the requested type, not it can't or never will.
///
/// # Examples
///

View file

@ -353,10 +353,10 @@ impl FormattingOptions {
/// Sets or removes the sign (the `+` or the `-` flag).
///
/// - `+`: This is intended for numeric types and indicates that the sign
/// should always be printed. By default only the negative sign of signed
/// values is printed, and the sign of positive or unsigned values is
/// omitted. This flag indicates that the correct sign (+ or -) should
/// always be printed.
/// should always be printed. By default only the negative sign of signed
/// values is printed, and the sign of positive or unsigned values is
/// omitted. This flag indicates that the correct sign (+ or -) should
/// always be printed.
/// - `-`: Currently not used
#[unstable(feature = "formatting_options", issue = "118117")]
pub fn sign(&mut self, sign: Option<Sign>) -> &mut Self {
@ -443,9 +443,9 @@ impl FormattingOptions {
/// Sets or removes the precision.
///
/// - For non-numeric types, this can be considered a “maximum width”. If
/// the resulting string is longer than this width, then it is truncated
/// down to this many characters and that truncated value is emitted with
/// proper fill, alignment and width if those parameters are set.
/// the resulting string is longer than this width, then it is truncated
/// down to this many characters and that truncated value is emitted with
/// proper fill, alignment and width if those parameters are set.
/// - For integral types, this is ignored.
/// - For floating-point types, this indicates how many digits after the
/// decimal point should be printed.

View file

@ -211,8 +211,8 @@ pub trait PointeeSized {
/// - The type is sized.
/// - The type outlives `'a`.
/// - Structs `Foo<..., T1, ..., Tn, ...>` implement `Unsize<Foo<..., U1, ..., Un, ...>>`
/// where any number of (type and const) parameters may be changed if all of these conditions
/// are met:
/// where any number of (type and const) parameters may be changed if all of these conditions
/// are met:
/// - Only the last field of `Foo` has a type involving the parameters `T1`, ..., `Tn`.
/// - All other parameters of the struct are equal.
/// - `Field<T1, ..., Tn>: Unsize<Field<U1, ..., Un>>`, where `Field<...>` stands for the actual

View file

@ -11,7 +11,7 @@
/// This destructor consists of two components:
/// - A call to `Drop::drop` for that value, if this special `Drop` trait is implemented for its type.
/// - The automatically generated "drop glue" which recursively calls the destructors
/// of all the fields of this value.
/// of all the fields of this value.
///
/// As Rust automatically calls the destructors of all contained fields,
/// you don't have to implement `Drop` in most cases. But there are some cases where

View file

@ -125,6 +125,7 @@
//! `Option::<T>::None`
//! - `transmute::<_, [u8; size_of::<T>()]>(Option::<T>::None)` is sound and produces
//! `[0u8; size_of::<T>()]`
//!
//! These cases are identified by the second column:
//!
//! | `T` | Transmuting between `[0u8; size_of::<T>()]` and `Option::<T>::None` sound? |

View file

@ -137,10 +137,10 @@
//! 2. An operation causes the value to depend on its own address not changing
//! * e.g. calling [`poll`] for the first time on the produced [`Future`]
//! 3. Further pieces of the safe interface of the type use internal [`unsafe`] operations which
//! assume that the address of the value is stable
//! assume that the address of the value is stable
//! * e.g. subsequent calls to [`poll`]
//! 4. Before the value is invalidated (e.g. deallocated), it is *dropped*, giving it a chance to
//! notify anything with pointers to itself that those pointers will be invalidated
//! notify anything with pointers to itself that those pointers will be invalidated
//! * e.g. [`drop`]ping the [`Future`] [^pin-drop-future]
//!
//! There are two possible ways to ensure the invariants required for 2. and 3. above (which
@ -148,8 +148,8 @@
//!
//! 1. Have the value detect when it is moved and update all the pointers that point to itself.
//! 2. Guarantee that the address of the value does not change (and that memory is not re-used
//! for anything else) during the time that the pointers to it are expected to be valid to
//! dereference.
//! for anything else) during the time that the pointers to it are expected to be valid to
//! dereference.
//!
//! Since, as we discussed, Rust can move values without notifying them that they have moved, the
//! first option is ruled out.
@ -160,11 +160,11 @@
//! be able to enforce this invariant in Rust:
//!
//! 1. Offer a wholly `unsafe` API to interact with the object, thus requiring every caller to
//! uphold the invariant themselves
//! uphold the invariant themselves
//! 2. Store the value that must not be moved behind a carefully managed pointer internal to
//! the object
//! the object
//! 3. Leverage the type system to encode and enforce this invariant by presenting a restricted
//! API surface to interact with *any* object that requires these invariants
//! API surface to interact with *any* object that requires these invariants
//!
//! The first option is quite obviously undesirable, as the [`unsafe`]ty of the interface will
//! become viral throughout all code that interacts with the object.
@ -530,7 +530,7 @@
//! but it also implies that,
//!
//! 2. The memory location that stores the value must not get invalidated or otherwise repurposed
//! during the lifespan of the pinned value until its [`drop`] returns or panics
//! during the lifespan of the pinned value until its [`drop`] returns or panics
//!
//! This point is subtle but required for intrusive data structures to be implemented soundly.
//!

View file

@ -739,19 +739,29 @@ def configure_file(sections, top_level_keys, targets, config):
def write_uncommented(target, f):
"""Writes each block in 'target' that is not composed entirely of comments to 'f'.
A block is a sequence of non-empty lines separated by empty lines.
"""
block = []
is_comment = True
def flush(last):
# If the block is entirely made of comments, ignore it
entire_block_comments = all(ln.startswith("#") or ln == "" for ln in block)
if not entire_block_comments and len(block) > 0:
for line in block:
f.write(line + "\n")
# Required to output a newline before the start of a new section
if last:
f.write("\n")
block.clear()
for line in target:
block.append(line)
if len(line) == 0:
if not is_comment:
for ln in block:
f.write(ln + "\n")
block = []
is_comment = True
continue
is_comment = is_comment and line.startswith("#")
flush(last=False)
flush(last=True)
return f

View file

@ -2057,14 +2057,20 @@ impl Step for Assemble {
trace!("llvm-bitcode-linker enabled, installing");
let llvm_bitcode_linker =
builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker {
compiler,
build_compiler: compiler,
target: target_compiler.host,
extra_features: vec![],
});
// Copy the llvm-bitcode-linker to the self-contained binary directory
let bindir_self_contained = builder
.sysroot(compiler)
.join(format!("lib/rustlib/{}/bin/self-contained", compiler.host));
let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
t!(fs::create_dir_all(&bindir_self_contained));
builder.copy_link(
&llvm_bitcode_linker.tool_path,
&libdir_bin.join(tool_exe),
&bindir_self_contained.join(tool_exe),
FileType::Executable,
);
}

View file

@ -2375,7 +2375,7 @@ impl Step for LlvmBitcodeLinker {
builder.ensure(compile::Rustc::new(compiler, target));
let llbc_linker =
builder.ensure(tool::LlvmBitcodeLinker { compiler, target, extra_features: vec![] });
builder.ensure(tool::LlvmBitcodeLinker { build_compiler: compiler, target });
let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);

View file

@ -910,6 +910,13 @@ impl Step for LldWrapper {
tool_result
}
fn metadata(&self) -> Option<StepMetadata> {
Some(
StepMetadata::build("LldWrapper", self.target_compiler.host)
.built_by(self.build_compiler),
)
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
@ -1014,9 +1021,8 @@ impl Step for RustAnalyzerProcMacroSrv {
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct LlvmBitcodeLinker {
pub compiler: Compiler,
pub build_compiler: Compiler,
pub target: TargetSelection,
pub extra_features: Vec<String>,
}
impl Step for LlvmBitcodeLinker {
@ -1032,8 +1038,9 @@ impl Step for LlvmBitcodeLinker {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(LlvmBitcodeLinker {
compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target),
extra_features: Vec::new(),
build_compiler: run
.builder
.compiler(run.builder.top_stage, run.builder.config.host_target),
target: run.target,
});
}
@ -1043,35 +1050,22 @@ impl Step for LlvmBitcodeLinker {
instrument(level = "debug", name = "LlvmBitcodeLinker::run", skip_all)
)]
fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
let tool_result = builder.ensure(ToolBuild {
compiler: self.compiler,
builder.ensure(ToolBuild {
compiler: self.build_compiler,
target: self.target,
tool: "llvm-bitcode-linker",
mode: Mode::ToolRustc,
path: "src/tools/llvm-bitcode-linker",
source_type: SourceType::InTree,
extra_features: self.extra_features,
extra_features: vec![],
allow_features: "",
cargo_args: Vec::new(),
artifact_kind: ToolArtifactKind::Binary,
});
})
}
if tool_result.target_compiler.stage > 0 {
let bindir_self_contained = builder
.sysroot(tool_result.target_compiler)
.join(format!("lib/rustlib/{}/bin/self-contained", self.target.triple));
t!(fs::create_dir_all(&bindir_self_contained));
let bin_destination = bindir_self_contained
.join(exe("llvm-bitcode-linker", tool_result.target_compiler.host));
builder.copy_link(&tool_result.tool_path, &bin_destination, FileType::Executable);
ToolBuildResult {
tool_path: bin_destination,
build_compiler: tool_result.build_compiler,
target_compiler: tool_result.target_compiler,
}
} else {
tool_result
}
fn metadata(&self) -> Option<StepMetadata> {
Some(StepMetadata::build("LlvmBitcodeLinker", self.target).built_by(self.build_compiler))
}
}

View file

@ -757,6 +757,58 @@ mod snapshot {
");
}
#[test]
fn build_compiler_tools() {
let ctx = TestCtx::new();
insta::assert_snapshot!(
ctx
.config("build")
.stage(2)
.args(&["--set", "rust.lld=true", "--set", "rust.llvm-bitcode-linker=true"])
.render_steps(), @r"
[build] llvm <host>
[build] rustc 0 <host> -> rustc 1 <host>
[build] rustc 0 <host> -> LldWrapper 1 <host>
[build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
[build] rustc 1 <host> -> std 1 <host>
[build] rustc 1 <host> -> rustc 2 <host>
[build] rustc 1 <host> -> LldWrapper 2 <host>
[build] rustc 2 <host> -> LlvmBitcodeLinker 3 <host>
[build] rustc 2 <host> -> std 2 <host>
[build] rustdoc 1 <host>
"
);
}
#[test]
fn build_compiler_tools_cross() {
let ctx = TestCtx::new();
insta::assert_snapshot!(
ctx
.config("build")
.stage(2)
.args(&["--set", "rust.lld=true", "--set", "rust.llvm-bitcode-linker=true"])
.hosts(&[TEST_TRIPLE_1])
.render_steps(), @r"
[build] llvm <host>
[build] rustc 0 <host> -> rustc 1 <host>
[build] rustc 0 <host> -> LldWrapper 1 <host>
[build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
[build] rustc 1 <host> -> std 1 <host>
[build] rustc 1 <host> -> rustc 2 <host>
[build] rustc 1 <host> -> LldWrapper 2 <host>
[build] rustc 2 <host> -> LlvmBitcodeLinker 3 <host>
[build] rustc 1 <host> -> std 1 <target1>
[build] rustc 2 <host> -> std 2 <target1>
[build] llvm <target1>
[build] rustc 1 <host> -> rustc 2 <target1>
[build] rustc 1 <host> -> LldWrapper 2 <target1>
[build] rustc 2 <target1> -> LlvmBitcodeLinker 3 <target1>
[build] rustdoc 1 <target1>
"
);
}
#[test]
fn build_library_no_explicit_stage() {
let ctx = TestCtx::new();
@ -1040,6 +1092,7 @@ mod snapshot {
[build] rustc 0 <host> -> cargo-clippy 1 <host>
[build] rustc 0 <host> -> miri 1 <host>
[build] rustc 0 <host> -> cargo-miri 1 <host>
[build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
");
}
@ -1230,6 +1283,7 @@ mod snapshot {
[build] rustc 0 <host> -> cargo-clippy 1 <target1>
[build] rustc 0 <host> -> miri 1 <target1>
[build] rustc 0 <host> -> cargo-miri 1 <target1>
[build] rustc 1 <host> -> LlvmBitcodeLinker 2 <target1>
");
}

View file

@ -96,8 +96,6 @@ impl ConfigBuilder {
// in-tree LLVM from sources.
self.args.push("--set".to_string());
self.args.push("llvm.download-ci-llvm=false".to_string());
self.args.push("--set".to_string());
self.args.push(format!("target.'{}'.llvm-config=false", get_host_target()));
// Do not mess with the local rustc checkout build directory
self.args.push("--build-dir".to_string());

View file

@ -1014,8 +1014,6 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
const PANIC_ON_ALLOC_FAIL: bool = false;
const TRACING_ENABLED: bool = cfg!(feature = "tracing");
#[inline(always)]
fn enforce_alignment(ecx: &MiriInterpCx<'tcx>) -> bool {
ecx.machine.check_alignment != AlignmentCheck::None
@ -1827,6 +1825,16 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
#[cfg(not(target_os = "linux"))]
MiriAllocParams::Global
}
fn enter_trace_span(span: impl FnOnce() -> tracing::Span) -> impl EnteredTraceSpan {
#[cfg(feature = "tracing")]
{ span().entered() }
#[cfg(not(feature = "tracing"))]
{
let _ = span; // so we avoid the "unused variable" warning
()
}
}
}
/// Trait for callbacks handling asynchronous machine operations.

View file

@ -40,8 +40,6 @@ LL | fn qux(&self) {
error[E0424]: expected unit struct, unit variant or constant, found module `self`
--> $DIR/E0424.rs:20:9
|
LL | fn main () {
| ---- this function can't have a `self` parameter
LL | let self = "self";
| ^^^^ `self` value is a keyword and may not be bound to variables or shadowed

View file

@ -5,25 +5,24 @@
#![feature(f16)]
#![feature(f128)]
#![feature(cfg_target_has_reliable_f16_f128)]
#![allow(unused_macro_rules)]
// expect the unexpected (`target_has_reliable_*` are not "known" configs since they are unstable)
#![expect(unexpected_cfgs)]
use std::hint::black_box;
macro_rules! both_assert {
($a:expr) => {
{
const _: () = assert!($a);
// `black_box` prevents promotion, and MIR opts are disabled above, so this is truly
// going through LLVM.
assert!(black_box($a));
}
};
($a:expr, $b:expr) => {
{
const _: () = assert!($a == $b);
assert_eq!(black_box($a), black_box($b));
}
};
($a:expr) => {{
const _: () = assert!($a);
// `black_box` prevents promotion, and MIR opts are disabled above, so this is truly
// going through LLVM.
assert!(black_box($a));
}};
($a:expr, $b:expr) => {{
const _: () = assert!($a == $b);
assert_eq!(black_box($a), black_box($b));
}};
}
fn has_broken_floats() -> bool {
@ -31,8 +30,8 @@ fn has_broken_floats() -> bool {
cfg!(all(target_arch = "x86", not(target_feature = "sse2")))
}
#[cfg(target_arch = "x86_64")]
fn f16(){
#[cfg(target_has_reliable_f16)]
fn f16() {
both_assert!((1f16).to_bits(), 0x3c00);
both_assert!(u16::from_be_bytes(1f16.to_be_bytes()), 0x3c00);
both_assert!((12.5f16).to_bits(), 0x4a40);
@ -122,7 +121,7 @@ fn f64() {
}
}
#[cfg(target_arch = "x86_64")]
#[cfg(target_has_reliable_f128)]
fn f128() {
both_assert!((1f128).to_bits(), 0x3fff0000000000000000000000000000);
both_assert!(u128::from_be_bytes(1f128.to_be_bytes()), 0x3fff0000000000000000000000000000);
@ -154,12 +153,10 @@ fn f128() {
}
fn main() {
#[cfg(target_has_reliable_f16)]
f16();
f32();
f64();
#[cfg(target_arch = "x86_64")]
{
f16();
f128();
}
#[cfg(target_has_reliable_f128)]
f128();
}

View file

@ -1,6 +1,6 @@
//@ run-fail
//@ compile-flags: -C debug-assertions
//@ error-pattern: trying to construct an enum from an invalid value 0x10000
//@ error-pattern: trying to construct an enum from an invalid value
#[allow(dead_code)]
#[repr(u32)]
@ -11,10 +11,9 @@ enum Foo {
#[allow(dead_code)]
struct Bar {
a: u16,
b: u16,
a: u32,
}
fn main() {
let _val: Foo = unsafe { std::mem::transmute::<_, Foo>(Bar { a: 0, b: 1 }) };
let _val: Foo = unsafe { std::mem::transmute::<_, Foo>(Bar { a: 3 }) };
}

View file

@ -10,11 +10,10 @@ enum Foo {
#[allow(dead_code)]
struct Bar {
a: u16,
b: u16,
a: u32,
}
fn main() {
let _val: Foo = unsafe { std::mem::transmute::<_, Foo>(Bar { a: 0, b: 0 }) };
let _val: Foo = unsafe { std::mem::transmute::<_, Foo>(Bar { a: 1, b: 0 }) };
let _val: Foo = unsafe { std::mem::transmute::<_, Foo>(Bar { a: 0 }) };
let _val: Foo = unsafe { std::mem::transmute::<_, Foo>(Bar { a: 1 }) };
}

View file

@ -1,8 +1,9 @@
//@ run-fail
//@ compile-flags: -C debug-assertions
//@ error-pattern: trying to construct an enum from an invalid value 0x3
//@ error-pattern: trying to construct an enum from an invalid value
#[allow(dead_code)]
#[repr(u32)]
enum Foo {
A,
B,
@ -10,11 +11,11 @@ enum Foo {
#[allow(dead_code)]
struct Bar {
a: usize,
b: usize,
a: u32,
b: u32,
}
fn main() {
let _val: Option<(usize, Foo)> =
unsafe { std::mem::transmute::<_, Option<(usize, Foo)>>(Bar { a: 3, b: 3 }) };
let _val: Option<(u32, Foo)> =
unsafe { std::mem::transmute::<_, Option<(u32, Foo)>>(Bar { a: 3, b: 3 }) };
}

View file

@ -1,6 +1,6 @@
//@ run-fail
//@ compile-flags: -C debug-assertions
//@ error-pattern: trying to construct an enum from an invalid value 0x4
//@ error-pattern: trying to construct an enum from an invalid value
#[allow(dead_code)]
#[repr(u16)]
@ -17,5 +17,5 @@ enum Nested {
}
fn main() {
let _val: Nested = unsafe { std::mem::transmute::<u32, Nested>(4) };
let _val: Nested = unsafe { std::mem::transmute::<u32, Nested>(u32::MAX) };
}

View file

@ -0,0 +1,10 @@
trait T {
fn f(self);
}
impl T for () {
fn f(self) {
let self = (); //~ ERROR expected unit struct, unit variant or constant, found local variable `self`
}
}
fn main() {}

View file

@ -0,0 +1,9 @@
error[E0424]: expected unit struct, unit variant or constant, found local variable `self`
--> $DIR/false-self-in-macro-issue-143134.rs:6:13
|
LL | let self = ();
| ^^^^ `self` value is a keyword and may not be bound to variables or shadowed
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0424`.

View file

@ -0,0 +1,12 @@
// Regression test for #143523.
trait Trait {}
impl Trait for Vec<i32> {}
fn foo(_: impl Trait) {}
fn main() {
foo(&mut vec![1]);
//~^ ERROR the trait bound `&mut Vec<{integer}>: Trait` is not satisfied
}

View file

@ -0,0 +1,22 @@
error[E0277]: the trait bound `&mut Vec<{integer}>: Trait` is not satisfied
--> $DIR/suggest-remove-refs-6.rs:10:9
|
LL | foo(&mut vec![1]);
| --- ^^^^^^^^^^^^ the trait `Trait` is not implemented for `&mut Vec<{integer}>`
| |
| required by a bound introduced by this call
|
note: required by a bound in `foo`
--> $DIR/suggest-remove-refs-6.rs:7:16
|
LL | fn foo(_: impl Trait) {}
| ^^^^^ required by this bound in `foo`
help: consider removing the leading `&`-reference
|
LL - foo(&mut vec![1]);
LL + foo(vec![1]);
|
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,18 @@
// Regression test for #143481, where we were calling `predicates_of` on
// a Crate HIR node because we were using a dummy obligation cause's body id
// without checking that it was meaningful first.
trait Role {
type Inner;
}
struct HandshakeCallback<C>(C);
impl<C: Clone> Role for HandshakeCallback {
//~^ ERROR missing generics
type Inner = usize;
}
struct Handshake<R: Role>(R::Inner);
fn accept() -> Handshake<HandshakeCallback<()>> {
todo!()
}
fn main() {}

View file

@ -0,0 +1,19 @@
error[E0107]: missing generics for struct `HandshakeCallback`
--> $DIR/ambiguity-in-dropck-err-reporting.rs:9:25
|
LL | impl<C: Clone> Role for HandshakeCallback {
| ^^^^^^^^^^^^^^^^^ expected 1 generic argument
|
note: struct defined here, with 1 generic parameter: `C`
--> $DIR/ambiguity-in-dropck-err-reporting.rs:8:8
|
LL | struct HandshakeCallback<C>(C);
| ^^^^^^^^^^^^^^^^^ -
help: add missing generic argument
|
LL | impl<C: Clone> Role for HandshakeCallback<C> {
| +++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0107`.