Rollup merge of #110126 - compiler-errors:new-solver-safe-transmute, r=oli-obk
Support safe transmute in new solver Basically copies the same implementation as the old solver, but instead of looking for param types, we look for type or const placeholders.
This commit is contained in:
commit
87c9b3f35e
17 changed files with 1184 additions and 121 deletions
|
@ -225,6 +225,11 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<TyCtxt<'tcx>> + Copy + Eq {
|
|||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
fn consider_builtin_transmute_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
}
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
|
@ -373,6 +378,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
G::consider_builtin_discriminant_kind_candidate(self, goal)
|
||||
} else if lang_items.destruct_trait() == Some(trait_def_id) {
|
||||
G::consider_builtin_destruct_candidate(self, goal)
|
||||
} else if lang_items.transmute_trait() == Some(trait_def_id) {
|
||||
G::consider_builtin_transmute_candidate(self, goal)
|
||||
} else {
|
||||
Err(NoSolution)
|
||||
};
|
||||
|
|
|
@ -639,4 +639,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
crate::traits::wf::unnormalized_obligations(self.infcx, param_env, arg)
|
||||
.map(|obligations| obligations.into_iter().map(|obligation| obligation.into()))
|
||||
}
|
||||
|
||||
pub(super) fn is_transmutable(
|
||||
&self,
|
||||
src_and_dst: rustc_transmute::Types<'tcx>,
|
||||
scope: Ty<'tcx>,
|
||||
assume: rustc_transmute::Assume,
|
||||
) -> Result<Certainty, NoSolution> {
|
||||
// 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),
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -524,6 +524,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
|||
) -> QueryResult<'tcx> {
|
||||
bug!("`Destruct` does not have an associated type: {:?}", goal);
|
||||
}
|
||||
|
||||
fn consider_builtin_transmute_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx> {
|
||||
bug!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal)
|
||||
}
|
||||
}
|
||||
|
||||
/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
|
||||
|
|
|
@ -598,6 +598,35 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
|||
Err(NoSolution)
|
||||
}
|
||||
}
|
||||
|
||||
fn consider_builtin_transmute_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx> {
|
||||
// `rustc_transmute` does not have support for type or const params
|
||||
if goal.has_non_region_placeholders() {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// Erase regions because we compute layouts in `rustc_transmute`,
|
||||
// which will ICE for region vars.
|
||||
let substs = ecx.tcx().erase_regions(goal.predicate.trait_ref.substs);
|
||||
|
||||
let Some(assume) = rustc_transmute::Assume::from_const(
|
||||
ecx.tcx(),
|
||||
goal.param_env,
|
||||
substs.const_at(3),
|
||||
) else {
|
||||
return Err(NoSolution);
|
||||
};
|
||||
|
||||
let certainty = ecx.is_transmutable(
|
||||
rustc_transmute::Types { dst: substs.type_at(0), src: substs.type_at(1) },
|
||||
substs.type_at(2),
|
||||
assume,
|
||||
)?;
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(certainty)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue