Erase regions when confirming transmutability candidate
This commit is contained in:
parent
8a778ca1e3
commit
f6bfb4bf8e
8 changed files with 88 additions and 44 deletions
|
@ -649,7 +649,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
// FIXME(transmutability): This really should be returning nested goals for `Answer::If*`
|
||||
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
|
||||
ObligationCause::dummy(),
|
||||
ty::Binder::dummy(src_and_dst),
|
||||
src_and_dst,
|
||||
scope,
|
||||
assume,
|
||||
) {
|
||||
|
|
|
@ -742,7 +742,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
{
|
||||
// Recompute the safe transmute reason and use that for the error reporting
|
||||
self.get_safe_transmute_error_and_reason(
|
||||
trait_predicate,
|
||||
obligation.clone(),
|
||||
trait_ref,
|
||||
span,
|
||||
|
@ -1629,7 +1628,6 @@ trait InferCtxtPrivExt<'tcx> {
|
|||
|
||||
fn get_safe_transmute_error_and_reason(
|
||||
&self,
|
||||
trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
|
||||
obligation: Obligation<'tcx, ty::Predicate<'tcx>>,
|
||||
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
span: Span,
|
||||
|
@ -2921,18 +2919,20 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
fn get_safe_transmute_error_and_reason(
|
||||
&self,
|
||||
trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
|
||||
obligation: Obligation<'tcx, ty::Predicate<'tcx>>,
|
||||
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
span: Span,
|
||||
) -> (String, Option<String>) {
|
||||
let src_and_dst = trait_predicate.map_bound(|p| rustc_transmute::Types {
|
||||
dst: p.trait_ref.substs.type_at(0),
|
||||
src: p.trait_ref.substs.type_at(1),
|
||||
});
|
||||
let scope = trait_ref.skip_binder().substs.type_at(2);
|
||||
// Erase regions because layout code doesn't particularly care about regions.
|
||||
let trait_ref = self.tcx.erase_regions(self.tcx.erase_late_bound_regions(trait_ref));
|
||||
|
||||
let src_and_dst = rustc_transmute::Types {
|
||||
dst: trait_ref.substs.type_at(0),
|
||||
src: trait_ref.substs.type_at(1),
|
||||
};
|
||||
let scope = trait_ref.substs.type_at(2);
|
||||
let Some(assume) =
|
||||
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, trait_ref.skip_binder().substs.const_at(3)) else {
|
||||
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");
|
||||
};
|
||||
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
|
||||
|
@ -2942,8 +2942,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
assume,
|
||||
) {
|
||||
rustc_transmute::Answer::No(reason) => {
|
||||
let dst = trait_ref.skip_binder().substs.type_at(0);
|
||||
let src = trait_ref.skip_binder().substs.type_at(1);
|
||||
let dst = trait_ref.substs.type_at(0);
|
||||
let src = trait_ref.substs.type_at(1);
|
||||
let custom_err_msg = format!(
|
||||
"`{src}` cannot be safely transmuted into `{dst}` in the defining scope of `{scope}`"
|
||||
);
|
||||
|
|
|
@ -275,33 +275,35 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
) -> Result<ImplSourceBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
|
||||
debug!(?obligation, "confirm_transmutability_candidate");
|
||||
|
||||
let predicate = obligation.predicate;
|
||||
// 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
|
||||
// to instantiating the binder with placeholders then erasing those
|
||||
// placeholder regions.
|
||||
let predicate =
|
||||
self.tcx().erase_regions(self.tcx().erase_late_bound_regions(obligation.predicate));
|
||||
|
||||
let type_at = |i| predicate.map_bound(|p| p.trait_ref.substs.type_at(i));
|
||||
let const_at = |i| predicate.skip_binder().trait_ref.substs.const_at(i);
|
||||
|
||||
let src_and_dst = predicate.map_bound(|p| rustc_transmute::Types {
|
||||
dst: p.trait_ref.substs.type_at(0),
|
||||
src: p.trait_ref.substs.type_at(1),
|
||||
});
|
||||
|
||||
let scope = type_at(2).skip_binder();
|
||||
|
||||
let Some(assume) =
|
||||
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, const_at(3)) else {
|
||||
return Err(Unimplemented);
|
||||
};
|
||||
|
||||
let cause = obligation.cause.clone();
|
||||
let Some(assume) = rustc_transmute::Assume::from_const(
|
||||
self.infcx.tcx,
|
||||
obligation.param_env,
|
||||
predicate.trait_ref.substs.const_at(3)
|
||||
) else {
|
||||
return Err(Unimplemented);
|
||||
};
|
||||
|
||||
let mut transmute_env = rustc_transmute::TransmuteTypeEnv::new(self.infcx);
|
||||
|
||||
let maybe_transmutable = transmute_env.is_transmutable(cause, src_and_dst, scope, assume);
|
||||
|
||||
use rustc_transmute::Answer;
|
||||
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),
|
||||
},
|
||||
predicate.trait_ref.substs.type_at(2),
|
||||
assume,
|
||||
);
|
||||
|
||||
match maybe_transmutable {
|
||||
Answer::Yes => Ok(ImplSourceBuiltinData { nested: vec![] }),
|
||||
rustc_transmute::Answer::Yes => Ok(ImplSourceBuiltinData { nested: vec![] }),
|
||||
_ => Err(Unimplemented),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue