Auto merge of #142358 - matthiaskrgr:rollup-fxe6m7k, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - rust-lang/rust#141967 (Configure bootstrap backport nominations through triagebot) - rust-lang/rust#142042 (Make E0621 missing lifetime suggestion verbose) - rust-lang/rust#142272 (tests: Change ABIs in tests to more future-resilient ones) - rust-lang/rust#142282 (Only run `citool` tests on the `auto` branch) - rust-lang/rust#142297 (Implement `//@ needs-target-std` compiletest directive) - rust-lang/rust#142298 (Make loongarch-none target maintainers more easily pingable) - rust-lang/rust#142306 (Dont unwrap and re-wrap typing envs) - rust-lang/rust#142324 (Remove unneeded `FunctionCx` from some codegen methods) - rust-lang/rust#142328 (feat: Add `bit_width` for unsigned integer types) Failed merges: - rust-lang/rust#141639 (Expose discriminant values in stable_mir) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
@@ -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,
|
||||
@@ -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
|
||||
@@ -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),
|
||||
@@ -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,
|
||||
@@ -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(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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()))
|
||||
};
|
||||
|
||||
@@ -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]
|
||||
@@ -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]
|
||||
@@ -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]
|
||||
@@ -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]
|
||||
|
||||
@@ -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.
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user