Remove allow(unused_variables) for rustc_transmute.

This was hiding some genuine sins, including unused arguments in
numerous functions/methods (incl. trait methods), and some unnecessary
computation.
This commit is contained in:
Nicholas Nethercote 2025-02-28 16:52:28 +11:00
parent dfb2222952
commit 785e21d382
10 changed files with 24 additions and 53 deletions

View file

@ -102,7 +102,6 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
fn is_transmutable(
&self,
param_env: <Self::Interner as Interner>::ParamEnv,
dst: <Self::Interner as Interner>::Ty,
src: <Self::Interner as Interner>::Ty,
assume: <Self::Interner as Interner>::Const,

View file

@ -1037,12 +1037,11 @@ where
pub(super) fn is_transmutable(
&mut self,
param_env: I::ParamEnv,
dst: I::Ty,
src: I::Ty,
assume: I::Const,
) -> Result<Certainty, NoSolution> {
self.delegate.is_transmutable(param_env, dst, src, assume)
self.delegate.is_transmutable(dst, src, assume)
}
}

View file

@ -617,7 +617,6 @@ where
)?;
let certainty = ecx.is_transmutable(
goal.param_env,
goal.predicate.trait_ref.args.type_at(0),
goal.predicate.trait_ref.args.type_at(1),
assume,

View file

@ -2530,9 +2530,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
return GetSafeTransmuteErrorAndReason::Silent;
};
let Some(assume) =
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, assume)
else {
let Some(assume) = rustc_transmute::Assume::from_const(self.infcx.tcx, assume) else {
self.dcx().span_delayed_bug(
span,
"Unable to construct rustc_transmute::Assume where it was previously possible",
@ -2544,11 +2542,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let src = trait_pred.trait_ref.args.type_at(1);
let err_msg = format!("`{src}` cannot be safely transmuted into `{dst}`");
match rustc_transmute::TransmuteTypeEnv::new(self.infcx.tcx).is_transmutable(
obligation.cause,
src_and_dst,
assume,
) {
match rustc_transmute::TransmuteTypeEnv::new(self.infcx.tcx)
.is_transmutable(src_and_dst, assume)
{
Answer::No(reason) => {
let safe_transmute_explanation = match reason {
rustc_transmute::Reason::SrcIsNotYetSupported => {

View file

@ -7,7 +7,6 @@ use rustc_infer::infer::canonical::{
Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarValues,
};
use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::solve::Goal;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt as _};
@ -222,7 +221,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
// register candidates. We probably need to register >1 since we may have an OR of ANDs.
fn is_transmutable(
&self,
param_env: ty::ParamEnv<'tcx>,
dst: Ty<'tcx>,
src: Ty<'tcx>,
assume: ty::Const<'tcx>,
@ -231,16 +229,14 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
// which will ICE for region vars.
let (dst, src) = self.tcx.erase_regions((dst, src));
let Some(assume) = rustc_transmute::Assume::from_const(self.tcx, param_env, assume) else {
let Some(assume) = rustc_transmute::Assume::from_const(self.tcx, assume) else {
return Err(NoSolution);
};
// FIXME(transmutability): This really should be returning nested goals for `Answer::If*`
match rustc_transmute::TransmuteTypeEnv::new(self.0.tcx).is_transmutable(
ObligationCause::dummy(),
rustc_transmute::Types { src, dst },
assume,
) {
match rustc_transmute::TransmuteTypeEnv::new(self.0.tcx)
.is_transmutable(rustc_transmute::Types { src, dst }, assume)
{
rustc_transmute::Answer::Yes => Ok(Certainty::Yes),
rustc_transmute::Answer::No(_) | rustc_transmute::Answer::If(_) => Err(NoSolution),
}

View file

@ -414,9 +414,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if self.tcx().features().generic_const_exprs() {
assume = crate::traits::evaluate_const(self.infcx, assume, obligation.param_env)
}
let Some(assume) =
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, assume)
else {
let Some(assume) = rustc_transmute::Assume::from_const(self.infcx.tcx, assume) else {
return Err(Unimplemented);
};
@ -425,11 +423,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?src, ?dst);
let mut transmute_env = rustc_transmute::TransmuteTypeEnv::new(self.infcx.tcx);
let maybe_transmutable = transmute_env.is_transmutable(
obligation.cause.clone(),
rustc_transmute::Types { dst, src },
assume,
);
let maybe_transmutable =
transmute_env.is_transmutable(rustc_transmute::Types { dst, src }, assume);
let fully_flattened = match maybe_transmutable {
Answer::No(_) => Err(Unimplemented)?,

View file

@ -237,7 +237,7 @@ pub(crate) mod rustc {
ty::Tuple(members) => Self::from_tuple((ty, layout), members, cx),
ty::Array(inner_ty, len) => {
ty::Array(inner_ty, _len) => {
let FieldsShape::Array { stride, count } = &layout.fields else {
return Err(Err::NotYetSupported);
};
@ -282,7 +282,6 @@ pub(crate) mod rustc {
FieldsShape::Primitive => {
assert_eq!(members.len(), 1);
let inner_ty = members[0];
let inner_layout = layout_of(cx, inner_ty)?;
Self::from_ty(inner_ty, cx)
}
FieldsShape::Arbitrary { offsets, .. } => {
@ -345,7 +344,7 @@ pub(crate) mod rustc {
// the enum delegates its layout to the variant at `index`.
layout_of_variant(*index, None)
}
Variants::Multiple { tag, tag_encoding, tag_field, .. } => {
Variants::Multiple { tag: _, tag_encoding, tag_field, .. } => {
// `Variants::Multiple` denotes an enum with multiple
// variants. The layout of such an enum is the disjunction
// of the layouts of its tagged variants.
@ -356,7 +355,7 @@ pub(crate) mod rustc {
let variants = def.discriminants(cx.tcx()).try_fold(
Self::uninhabited(),
|variants, (idx, ref discriminant)| {
|variants, (idx, _discriminant)| {
let variant = layout_of_variant(idx, Some(tag_encoding.clone()))?;
Result::<Self, Err>::Ok(variants.or(variant))
},
@ -414,7 +413,7 @@ pub(crate) mod rustc {
// Append the fields, in memory order, to the layout.
let inverse_memory_index = memory_index.invert_bijective_mapping();
for (memory_idx, &field_idx) in inverse_memory_index.iter_enumerated() {
for &field_idx in inverse_memory_index.iter() {
// Add interfield padding.
let padding_needed = offsets[field_idx] - size;
let padding = Self::padding(padding_needed.bytes_usize());
@ -468,15 +467,14 @@ pub(crate) mod rustc {
// This constructor does not support non-`FieldsShape::Union`
// layouts. Fields of this shape are all placed at offset 0.
let FieldsShape::Union(fields) = layout.fields() else {
let FieldsShape::Union(_fields) = layout.fields() else {
return Err(Err::NotYetSupported);
};
let fields = &def.non_enum_variant().fields;
let fields = fields.iter_enumerated().try_fold(
Self::uninhabited(),
|fields, (idx, field_def)| {
let field_def = Def::Field(field_def);
|fields, (idx, _field_def)| {
let field_ty = ty_field(cx, (ty, layout), idx);
let field_layout = layout_of(cx, field_ty)?;
let field = Self::from_ty(field_ty, cx)?;

View file

@ -1,5 +1,4 @@
// tidy-alphabetical-start
#![allow(unused_variables)]
#![feature(never_type)]
#![warn(unreachable_pub)]
// tidy-alphabetical-end
@ -80,8 +79,7 @@ pub enum Reason<T> {
#[cfg(feature = "rustc")]
mod rustc {
use rustc_hir::lang_items::LangItem;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{Const, ParamEnv, Ty, TyCtxt};
use rustc_middle::ty::{Const, Ty, TyCtxt};
use super::*;
@ -105,15 +103,11 @@ mod rustc {
pub fn is_transmutable(
&mut self,
cause: ObligationCause<'tcx>,
types: Types<'tcx>,
assume: crate::Assume,
) -> crate::Answer<crate::layout::rustc::Ref<'tcx>> {
crate::maybe_transmutable::MaybeTransmutableQuery::new(
types.src,
types.dst,
assume,
self.tcx,
types.src, types.dst, assume, self.tcx,
)
.answer()
}
@ -121,11 +115,7 @@ mod rustc {
impl Assume {
/// Constructs an `Assume` from a given const-`Assume`.
pub fn from_const<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
ct: Const<'tcx>,
) -> Option<Self> {
pub fn from_const<'tcx>(tcx: TyCtxt<'tcx>, ct: Const<'tcx>) -> Option<Self> {
use rustc_middle::ty::ScalarInt;
use rustc_span::sym;

View file

@ -79,12 +79,12 @@ where
pub(crate) fn answer(self) -> Answer<<C as QueryContext>::Ref> {
let Self { src, dst, assume, context } = self;
// Unconditionally all `Def` nodes from `src`, without pruning away the
// Unconditionally remove all `Def` nodes from `src`, without pruning away the
// branches they appear in. This is valid to do for value-to-value
// transmutations, but not for `&mut T` to `&mut U`; we will need to be
// more sophisticated to handle transmutations between mutable
// references.
let src = src.prune(&|def| false);
let src = src.prune(&|_def| false);
if src.is_inhabited() && !dst.is_inhabited() {
return Answer::No(Reason::DstUninhabited);
@ -96,7 +96,7 @@ where
let dst = if assume.safety {
// ...if safety is assumed, don't check if they carry safety
// invariants; retain all paths.
dst.prune(&|def| false)
dst.prune(&|_def| false)
} else {
// ...otherwise, prune away all paths with safety invariants from
// the `Dst` layout.

View file

@ -92,7 +92,6 @@ mod bool {
#[test]
fn should_permit_validity_expansion_and_reject_contraction() {
let un = layout::Tree::<Def, !>::uninhabited();
let b0 = layout::Tree::<Def, !>::from_bits(0);
let b1 = layout::Tree::<Def, !>::from_bits(1);
let b2 = layout::Tree::<Def, !>::from_bits(2);