Skip to content

Rollup of 9 pull requests #142358

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Jun 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3fce086
Make E0621 missing lifetime suggestion verbose
estebank Jun 4, 2025
643a9d2
tests: Change "fastcall" to "system" in some tests
workingjubilee Jun 6, 2025
518eb0d
rustdoc-json: Rearrange deck chairs in ABI testing
workingjubilee Jun 2, 2025
cb3d074
Only run `citool` tests on the `auto` branch
Kobzol Jun 10, 2025
8ef8062
Extract target no-std hack to `build_helpers`
jieyouxu Jun 10, 2025
e10b2f6
Implement `//@ needs-target-std` directive in compiletest
jieyouxu Jun 10, 2025
c5b8123
Document `//@ needs-target-std` in rustc-dev-guide
jieyouxu Jun 10, 2025
97270ed
Make loongarch-none target maintainers more easily pingable
jieyouxu Jun 10, 2025
c558db3
Modify some run-make tests to use `//@ needs-target-std`
jieyouxu Jun 10, 2025
6f48758
Configure bootstrap backport nominations via triagebot
jieyouxu Jun 3, 2025
6227acc
Dont unwrap and re-wrap typing envs
compiler-errors Jun 10, 2025
ed06f36
Remove unneeded `FunctionCx` from some codegen methods
scottmcm Jun 10, 2025
199b808
feat: Add `bit_width` for unsigned integer types
sorairolake Jun 7, 2025
471dee2
Rollup merge of #141967 - jieyouxu:bootstrap-backports, r=Kobzol
matthiaskrgr Jun 11, 2025
58d80b6
Rollup merge of #142042 - estebank:explicit-lifetime-verbose-suggesti…
matthiaskrgr Jun 11, 2025
90e4ba4
Rollup merge of #142272 - workingjubilee:change-some-abi-tests, r=aDo…
matthiaskrgr Jun 11, 2025
407e568
Rollup merge of #142282 - Kobzol:citool-skip-tests, r=marcoieni
matthiaskrgr Jun 11, 2025
57bb38b
Rollup merge of #142297 - jieyouxu:needs-target-std, r=Kobzol
matthiaskrgr Jun 11, 2025
80e294e
Rollup merge of #142298 - jieyouxu:loongarch-maintainer-list, r=fee1-…
matthiaskrgr Jun 11, 2025
9ef19dd
Rollup merge of #142306 - compiler-errors:nit-reveal-param-env-query,…
matthiaskrgr Jun 11, 2025
b1c668c
Rollup merge of #142324 - scottmcm:less-functioncx, r=workingjubilee
matthiaskrgr Jun 11, 2025
583a6e2
Rollup merge of #142328 - sorairolake:feature/uint-bit-width, r=tgross35
matthiaskrgr Jun 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,18 @@ jobs:
uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
with:
workspaces: src/ci/citool
- name: Test citool
# Only test citool on the auto branch, to reduce latency of the calculate matrix job
# on PR/try builds.
if: ${{ github.ref == 'refs/heads/auto' }}
run: |
cd src/ci/citool
CARGO_INCREMENTAL=0 cargo test
- name: Calculate the CI job matrix
env:
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
run: |
cd src/ci/citool
CARGO_INCREMENTAL=0 cargo test
CARGO_INCREMENTAL=0 cargo run calculate-job-matrix >> $GITHUB_OUTPUT
id: jobs
job:
Expand Down
190 changes: 94 additions & 96 deletions compiler/rustc_codegen_ssa/src/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
{
let from_backend_ty = bx.backend_type(operand.layout);
let to_backend_ty = bx.backend_type(cast);
Some(OperandValue::Immediate(self.transmute_immediate(
Some(OperandValue::Immediate(transmute_immediate(
bx,
imm,
from_scalar,
Expand All @@ -303,8 +303,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let out_a_ibty = bx.scalar_pair_element_backend_type(cast, 0, false);
let out_b_ibty = bx.scalar_pair_element_backend_type(cast, 1, false);
Some(OperandValue::Pair(
self.transmute_immediate(bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty),
self.transmute_immediate(bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty),
transmute_immediate(bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty),
transmute_immediate(bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty),
))
} else {
None
Expand Down Expand Up @@ -332,7 +332,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// valid ranges. For example, `char`s are passed as just `i32`, with no
// way for LLVM to know that they're 0x10FFFF at most. Thus we assume
// the range of the input value too, not just the output range.
self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
assume_scalar_range(bx, imm, from_scalar, from_backend_ty);

imm = match (from_scalar.primitive(), to_scalar.primitive()) {
(Int(_, is_signed), Int(..)) => bx.intcast(imm, to_backend_ty, is_signed),
Expand Down Expand Up @@ -365,98 +365,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
Some(imm)
}

/// Transmutes one of the immediates from an [`OperandValue::Immediate`]
/// or an [`OperandValue::Pair`] to an immediate of the target type.
///
/// `to_backend_ty` must be the *non*-immediate backend type (so it will be
/// `i8`, not `i1`, for `bool`-like types.)
fn transmute_immediate(
&self,
bx: &mut Bx,
mut imm: Bx::Value,
from_scalar: abi::Scalar,
from_backend_ty: Bx::Type,
to_scalar: abi::Scalar,
to_backend_ty: Bx::Type,
) -> Bx::Value {
assert_eq!(from_scalar.size(self.cx), to_scalar.size(self.cx));

// While optimizations will remove no-op transmutes, they might still be
// there in debug or things that aren't no-op in MIR because they change
// the Rust type but not the underlying layout/niche.
if from_scalar == to_scalar && from_backend_ty == to_backend_ty {
return imm;
}

use abi::Primitive::*;
imm = bx.from_immediate(imm);

// If we have a scalar, we must already know its range. Either
//
// 1) It's a parameter with `range` parameter metadata,
// 2) It's something we `load`ed with `!range` metadata, or
// 3) After a transmute we `assume`d the range (see below).
//
// That said, last time we tried removing this, it didn't actually help
// the rustc-perf results, so might as well keep doing it
// <https://github.com/rust-lang/rust/pull/135610#issuecomment-2599275182>
self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty);

imm = match (from_scalar.primitive(), to_scalar.primitive()) {
(Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty),
(Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty),
(Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm),
(Pointer(..), Int(..)) => {
// FIXME: this exposes the provenance, which shouldn't be necessary.
bx.ptrtoint(imm, to_backend_ty)
}
(Float(_), Pointer(..)) => {
let int_imm = bx.bitcast(imm, bx.cx().type_isize());
bx.ptradd(bx.const_null(bx.type_ptr()), int_imm)
}
(Pointer(..), Float(_)) => {
// FIXME: this exposes the provenance, which shouldn't be necessary.
let int_imm = bx.ptrtoint(imm, bx.cx().type_isize());
bx.bitcast(int_imm, to_backend_ty)
}
};

// This `assume` remains important for cases like (a conceptual)
// transmute::<u32, NonZeroU32>(x) == 0
// since it's never passed to something with parameter metadata (especially
// after MIR inlining) so the only way to tell the backend about the
// constraint that the `transmute` introduced is to `assume` it.
self.assume_scalar_range(bx, imm, to_scalar, to_backend_ty);

imm = bx.to_immediate_scalar(imm, to_scalar);
imm
}

fn assume_scalar_range(
&self,
bx: &mut Bx,
imm: Bx::Value,
scalar: abi::Scalar,
backend_ty: Bx::Type,
) {
if matches!(self.cx.sess().opts.optimize, OptLevel::No) || scalar.is_always_valid(self.cx) {
return;
}

match scalar.primitive() {
abi::Primitive::Int(..) => {
let range = scalar.valid_range(self.cx);
bx.assume_integer_range(imm, backend_ty, range);
}
abi::Primitive::Pointer(abi::AddressSpace::DATA)
if !scalar.valid_range(self.cx).contains(0) =>
{
bx.assume_nonnull(imm);
}
abi::Primitive::Pointer(..) | abi::Primitive::Float(..) => {}
}
}

pub(crate) fn codegen_rvalue_unsized(
&mut self,
bx: &mut Bx,
Expand Down Expand Up @@ -1231,3 +1139,93 @@ impl OperandValueKind {
})
}
}

/// Transmutes one of the immediates from an [`OperandValue::Immediate`]
/// or an [`OperandValue::Pair`] to an immediate of the target type.
///
/// `to_backend_ty` must be the *non*-immediate backend type (so it will be
/// `i8`, not `i1`, for `bool`-like types.)
fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
mut imm: Bx::Value,
from_scalar: abi::Scalar,
from_backend_ty: Bx::Type,
to_scalar: abi::Scalar,
to_backend_ty: Bx::Type,
) -> Bx::Value {
assert_eq!(from_scalar.size(bx.cx()), to_scalar.size(bx.cx()));

// While optimizations will remove no-op transmutes, they might still be
// there in debug or things that aren't no-op in MIR because they change
// the Rust type but not the underlying layout/niche.
if from_scalar == to_scalar && from_backend_ty == to_backend_ty {
return imm;
}

use abi::Primitive::*;
imm = bx.from_immediate(imm);

// If we have a scalar, we must already know its range. Either
//
// 1) It's a parameter with `range` parameter metadata,
// 2) It's something we `load`ed with `!range` metadata, or
// 3) After a transmute we `assume`d the range (see below).
//
// That said, last time we tried removing this, it didn't actually help
// the rustc-perf results, so might as well keep doing it
// <https://github.com/rust-lang/rust/pull/135610#issuecomment-2599275182>
assume_scalar_range(bx, imm, from_scalar, from_backend_ty);

imm = match (from_scalar.primitive(), to_scalar.primitive()) {
(Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty),
(Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty),
(Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm),
(Pointer(..), Int(..)) => {
// FIXME: this exposes the provenance, which shouldn't be necessary.
bx.ptrtoint(imm, to_backend_ty)
}
(Float(_), Pointer(..)) => {
let int_imm = bx.bitcast(imm, bx.cx().type_isize());
bx.ptradd(bx.const_null(bx.type_ptr()), int_imm)
}
(Pointer(..), Float(_)) => {
// FIXME: this exposes the provenance, which shouldn't be necessary.
let int_imm = bx.ptrtoint(imm, bx.cx().type_isize());
bx.bitcast(int_imm, to_backend_ty)
}
};

// This `assume` remains important for cases like (a conceptual)
// transmute::<u32, NonZeroU32>(x) == 0
// since it's never passed to something with parameter metadata (especially
// after MIR inlining) so the only way to tell the backend about the
// constraint that the `transmute` introduced is to `assume` it.
assume_scalar_range(bx, imm, to_scalar, to_backend_ty);

imm = bx.to_immediate_scalar(imm, to_scalar);
imm
}

fn assume_scalar_range<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
imm: Bx::Value,
scalar: abi::Scalar,
backend_ty: Bx::Type,
) {
if matches!(bx.cx().sess().opts.optimize, OptLevel::No) || scalar.is_always_valid(bx.cx()) {
return;
}

match scalar.primitive() {
abi::Primitive::Int(..) => {
let range = scalar.valid_range(bx.cx());
bx.assume_integer_range(imm, backend_ty, range);
}
abi::Primitive::Pointer(abi::AddressSpace::DATA)
if !scalar.valid_range(bx.cx()).contains(0) =>
{
bx.assume_nonnull(imm);
}
abi::Primitive::Pointer(..) | abi::Primitive::Float(..) => {}
}
}
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/query/erase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ tcx_lifetime! {
rustc_middle::ty::layout::FnAbiError,
rustc_middle::ty::layout::LayoutError,
rustc_middle::ty::ParamEnv,
rustc_middle::ty::TypingEnv,
rustc_middle::ty::Predicate,
rustc_middle::ty::SymbolName,
rustc_middle::ty::TraitRef,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1566,7 +1566,7 @@ rustc_queries! {
/// Like `param_env`, but returns the `ParamEnv` after all opaque types have been
/// replaced with their hidden type. This is used in the old trait solver
/// when in `PostAnalysis` mode and should not be called directly.
query param_env_normalized_for_post_analysis(def_id: DefId) -> ty::ParamEnv<'tcx> {
query typing_env_normalized_for_post_analysis(def_id: DefId) -> ty::TypingEnv<'tcx> {
desc { |tcx| "computing revealed normalized predicates of `{}`", tcx.def_path_str(def_id) }
}

Expand Down
7 changes: 2 additions & 5 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1116,10 +1116,7 @@ impl<'tcx> TypingEnv<'tcx> {
}

pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryParam<DefId>) -> TypingEnv<'tcx> {
TypingEnv {
typing_mode: TypingMode::PostAnalysis,
param_env: tcx.param_env_normalized_for_post_analysis(def_id),
}
tcx.typing_env_normalized_for_post_analysis(def_id)
}

/// Modify the `typing_mode` to `PostAnalysis` and eagerly reveal all
Expand All @@ -1133,7 +1130,7 @@ impl<'tcx> TypingEnv<'tcx> {
// No need to reveal opaques with the new solver enabled,
// since we have lazy norm.
let param_env = if tcx.next_trait_solver_globally() {
ParamEnv::new(param_env.caller_bounds())
param_env
} else {
ParamEnv::new(tcx.reveal_opaque_types_in_bounds(param_env.caller_bounds()))
};
Expand Down
12 changes: 8 additions & 4 deletions compiler/rustc_trait_selection/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,8 @@ pub enum ExplicitLifetimeRequired<'a> {
#[suggestion(
trait_selection_explicit_lifetime_required_sugg_with_ident,
code = "{new_ty}",
applicability = "unspecified"
applicability = "unspecified",
style = "verbose"
)]
new_ty_span: Span,
#[skip_arg]
Expand All @@ -774,7 +775,8 @@ pub enum ExplicitLifetimeRequired<'a> {
#[suggestion(
trait_selection_explicit_lifetime_required_sugg_with_param_type,
code = "{new_ty}",
applicability = "unspecified"
applicability = "unspecified",
style = "verbose"
)]
new_ty_span: Span,
#[skip_arg]
Expand Down Expand Up @@ -1462,7 +1464,8 @@ pub enum SuggestAccessingField<'a> {
#[suggestion(
trait_selection_suggest_accessing_field,
code = "{snippet}.{name}",
applicability = "maybe-incorrect"
applicability = "maybe-incorrect",
style = "verbose"
)]
Safe {
#[primary_span]
Expand All @@ -1474,7 +1477,8 @@ pub enum SuggestAccessingField<'a> {
#[suggestion(
trait_selection_suggest_accessing_field,
code = "unsafe {{ {snippet}.{name} }}",
applicability = "maybe-incorrect"
applicability = "maybe-incorrect",
style = "verbose"
)]
Unsafe {
#[primary_span]
Expand Down
8 changes: 3 additions & 5 deletions compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
}
}

fn param_env_normalized_for_post_analysis(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
// This is a bit ugly but the easiest way to avoid code duplication.
let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id);
typing_env.with_post_analysis_normalized(tcx).param_env
fn typing_env_normalized_for_post_analysis(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TypingEnv<'_> {
ty::TypingEnv::non_body_analysis(tcx, def_id).with_post_analysis_normalized(tcx)
}

/// Check if a function is async.
Expand Down Expand Up @@ -374,7 +372,7 @@ pub(crate) fn provide(providers: &mut Providers) {
asyncness,
adt_sized_constraint,
param_env,
param_env_normalized_for_post_analysis,
typing_env_normalized_for_post_analysis,
defaultness,
unsizing_params_for_adt,
impl_self_is_guaranteed_unsized,
Expand Down
24 changes: 24 additions & 0 deletions library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,30 @@ macro_rules! uint_impl {
(!self).trailing_zeros()
}

/// Returns the minimum number of bits required to represent `self`.
///
/// This method returns zero if `self` is zero.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(uint_bit_width)]
///
#[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".bit_width(), 0);")]
#[doc = concat!("assert_eq!(0b111_", stringify!($SelfT), ".bit_width(), 3);")]
#[doc = concat!("assert_eq!(0b1110_", stringify!($SelfT), ".bit_width(), 4);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.bit_width(), ", stringify!($BITS), ");")]
/// ```
#[unstable(feature = "uint_bit_width", issue = "142326")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
pub const fn bit_width(self) -> u32 {
Self::BITS - self.leading_zeros()
}

/// Returns `self` with only the most significant bit set, or `0` if
/// the input is `0`.
///
Expand Down
1 change: 1 addition & 0 deletions library/coretests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
#![feature(try_blocks)]
#![feature(try_find)]
#![feature(try_trait_v2)]
#![feature(uint_bit_width)]
#![feature(unsize)]
#![feature(unwrap_infallible)]
// tidy-alphabetical-end
Expand Down
8 changes: 8 additions & 0 deletions library/coretests/tests/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ macro_rules! uint_module {
assert_eq_const_safe!(u32: X.trailing_ones(), 0);
}

fn test_bit_width() {
assert_eq_const_safe!(u32: A.bit_width(), 6);
assert_eq_const_safe!(u32: B.bit_width(), 6);
assert_eq_const_safe!(u32: C.bit_width(), 7);
assert_eq_const_safe!(u32: _0.bit_width(), 0);
assert_eq_const_safe!(u32: _1.bit_width(), $T::BITS);
}

fn test_rotate() {
assert_eq_const_safe!($T: A.rotate_left(6).rotate_right(2).rotate_right(4), A);
assert_eq_const_safe!($T: B.rotate_left(3).rotate_left(2).rotate_right(5), B);
Expand Down
Loading
Loading