1
Fork 0

Safe Transmute: Change Answer type to Result

This patch updates the `Answer` type from `rustc_transmute` so that it just a
type alias to `Result`. This makes it so that the standard methods for `Result`
can be used to process the `Answer` tree, including being able to make use of
the `?` operator on `Answer`s.

Also, remove some unused functions
This commit is contained in:
Bryan Garza 2023-04-27 14:38:32 -07:00
parent 8f1cec8d84
commit 263a4f2cb6
6 changed files with 113 additions and 140 deletions

View file

@ -675,11 +675,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
scope,
assume,
) {
rustc_transmute::Answer::Yes => Ok(Certainty::Yes),
rustc_transmute::Answer::No(_)
| rustc_transmute::Answer::IfTransmutable { .. }
| rustc_transmute::Answer::IfAll(_)
| rustc_transmute::Answer::IfAny(_) => Err(NoSolution),
Ok(None) => Ok(Certainty::Yes),
Err(_)
| Ok(Some(rustc_transmute::Condition::IfTransmutable { .. }))
| Ok(Some(rustc_transmute::Condition::IfAll(_)))
| Ok(Some(rustc_transmute::Condition::IfAny(_))) => Err(NoSolution),
}
}
}

View file

@ -2751,13 +2751,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, trait_ref.substs.const_at(3)) else {
span_bug!(span, "Unable to construct rustc_transmute::Assume where it was previously possible");
};
// FIXME(bryangarza): Need to flatten here too
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
obligation.cause,
src_and_dst,
scope,
assume,
) {
rustc_transmute::Answer::No(reason) => {
Err(reason) => {
let dst = trait_ref.substs.type_at(0);
let src = trait_ref.substs.type_at(1);
let custom_err_msg = format!(
@ -2795,7 +2796,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
(custom_err_msg, Some(reason_msg))
}
// Should never get a Yes at this point! We already ran it before, and did not get a Yes.
rustc_transmute::Answer::Yes => span_bug!(
Ok(None) => span_bug!(
span,
"Inconsistent rustc_transmute::is_transmutable(...) result, got Yes",
),

View file

@ -279,11 +279,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ImplSourceBuiltinData { nested: obligations }
}
#[instrument(skip(self))]
#[instrument(level = "debug", skip(self))]
fn confirm_transmutability_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
) -> Result<ImplSourceBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
#[instrument(level = "debug", skip(tcx, obligation, predicate))]
fn flatten_answer_tree<'tcx>(
tcx: TyCtxt<'tcx>,
obligation: &TraitObligation<'tcx>,
@ -291,11 +292,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
answer: rustc_transmute::Answer<rustc_transmute::layout::rustc::Ref<'tcx>>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
match answer {
rustc_transmute::Answer::Yes => Ok(vec![]),
rustc_transmute::Answer::No(_) => Err(Unimplemented),
Ok(None) => Ok(vec![]),
Err(_) => Err(Unimplemented),
// FIXME(bryangarza): Add separate `IfAny` case, instead of treating as `IfAll`
rustc_transmute::Answer::IfAll(answers)
| rustc_transmute::Answer::IfAny(answers) => {
Ok(Some(rustc_transmute::Condition::IfAll(answers)))
| Ok(Some(rustc_transmute::Condition::IfAny(answers))) => {
let mut nested = vec![];
for flattened in answers
.into_iter()
@ -305,7 +306,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
Ok(nested)
}
rustc_transmute::Answer::IfTransmutable { src, dst } => {
Ok(Some(rustc_transmute::Condition::IfTransmutable { src, dst })) => {
let trait_def_id = obligation.predicate.def_id();
let scope = predicate.trait_ref.substs.type_at(2);
let assume_const = predicate.trait_ref.substs.const_at(3);
@ -334,8 +335,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
debug!(?obligation, "confirm_transmutability_candidate");
// We erase regions here because transmutability calls layout queries,
// which does not handle inference regions and doesn't particularly
// care about other regions. Erasing late-bound regions is equivalent
@ -352,21 +351,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return Err(Unimplemented);
};
let dst = predicate.trait_ref.substs.type_at(0);
let src = predicate.trait_ref.substs.type_at(1);
let mut transmute_env = rustc_transmute::TransmuteTypeEnv::new(self.infcx);
let maybe_transmutable = transmute_env.is_transmutable(
obligation.cause.clone(),
rustc_transmute::Types {
dst: predicate.trait_ref.substs.type_at(0),
src: predicate.trait_ref.substs.type_at(1),
},
rustc_transmute::Types { dst, src },
predicate.trait_ref.substs.type_at(2),
assume,
);
info!(?maybe_transmutable);
let nested = flatten_answer_tree(self.tcx(), obligation, predicate, maybe_transmutable)?;
info!(?nested);
Ok(ImplSourceBuiltinData { nested })
debug!(?src, ?dst);
let fully_flattened =
flatten_answer_tree(self.tcx(), obligation, predicate, maybe_transmutable)?;
debug!(?fully_flattened);
Ok(ImplSourceBuiltinData { nested: fully_flattened })
}
/// This handles the case where an `auto trait Foo` impl is being used.