1
Fork 0

safe transmute: revise safety analysis

Migrate to a simplified safety analysis that does not use visibility.

Closes https://github.com/rust-lang/project-safe-transmute/issues/15
This commit is contained in:
Jack Wrenn 2024-02-26 16:49:25 +00:00
parent 9afdb8d1d5
commit 23ab1bda92
127 changed files with 1387 additions and 1948 deletions

View file

@ -874,7 +874,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
pub(super) fn is_transmutable(
&self,
src_and_dst: rustc_transmute::Types<'tcx>,
scope: Ty<'tcx>,
assume: rustc_transmute::Assume,
) -> Result<Certainty, NoSolution> {
use rustc_transmute::Answer;
@ -882,7 +881,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
ObligationCause::dummy(),
src_and_dst,
scope,
assume,
) {
Answer::Yes => Ok(Certainty::Yes),

View file

@ -543,14 +543,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
let args = ecx.tcx().erase_regions(goal.predicate.trait_ref.args);
let Some(assume) =
rustc_transmute::Assume::from_const(ecx.tcx(), goal.param_env, args.const_at(3))
rustc_transmute::Assume::from_const(ecx.tcx(), goal.param_env, args.const_at(2))
else {
return Err(NoSolution);
};
let certainty = ecx.is_transmutable(
rustc_transmute::Types { dst: args.type_at(0), src: args.type_at(1) },
args.type_at(2),
assume,
)?;
ecx.evaluate_added_goals_and_make_canonical_response(certainty)

View file

@ -2970,11 +2970,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
dst: trait_ref.args.type_at(0),
src: trait_ref.args.type_at(1),
};
let scope = trait_ref.args.type_at(2);
let Some(assume) = rustc_transmute::Assume::from_const(
self.infcx.tcx,
obligation.param_env,
trait_ref.args.const_at(3),
trait_ref.args.const_at(2),
) else {
self.dcx().span_delayed_bug(
span,
@ -2986,15 +2985,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
obligation.cause,
src_and_dst,
scope,
assume,
) {
Answer::No(reason) => {
let dst = trait_ref.args.type_at(0);
let src = trait_ref.args.type_at(1);
let err_msg = format!(
"`{src}` cannot be safely transmuted into `{dst}` in the defining scope of `{scope}`"
);
let err_msg = format!("`{src}` cannot be safely transmuted into `{dst}`");
let safe_transmute_explanation = match reason {
rustc_transmute::Reason::SrcIsUnspecified => {
format!("`{src}` does not have a well-specified layout")
@ -3008,9 +3004,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
format!("At least one value of `{src}` isn't a bit-valid value of `{dst}`")
}
rustc_transmute::Reason::DstIsPrivate => format!(
"`{dst}` is or contains a type or field that is not visible in that scope"
),
rustc_transmute::Reason::DstMayHaveSafetyInvariants => {
format!("`{dst}` may carry safety invariants")
}
rustc_transmute::Reason::DstIsTooBig => {
format!("The size of `{src}` is smaller than the size of `{dst}`")
}

View file

@ -310,8 +310,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.collect(),
Condition::IfTransmutable { src, dst } => {
let trait_def_id = obligation.predicate.def_id();
let scope = predicate.trait_ref.args.type_at(2);
let assume_const = predicate.trait_ref.args.const_at(3);
let assume_const = predicate.trait_ref.args.const_at(2);
let make_obl = |from_ty, to_ty| {
let trait_ref1 = ty::TraitRef::new(
tcx,
@ -319,7 +318,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
[
ty::GenericArg::from(to_ty),
ty::GenericArg::from(from_ty),
ty::GenericArg::from(scope),
ty::GenericArg::from(assume_const),
],
);
@ -355,7 +353,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let Some(assume) = rustc_transmute::Assume::from_const(
self.infcx.tcx,
obligation.param_env,
predicate.trait_ref.args.const_at(3),
predicate.trait_ref.args.const_at(2),
) else {
return Err(Unimplemented);
};
@ -367,7 +365,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let maybe_transmutable = transmute_env.is_transmutable(
obligation.cause.clone(),
rustc_transmute::Types { dst, src },
predicate.trait_ref.args.type_at(2),
assume,
);