mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 23:34:48 +00:00
Support safe transmute in new solver
This commit is contained in:
parent
2a198c7f62
commit
d92f74e43b
@ -83,6 +83,9 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
|
||||
| TypeFlags::HAS_CT_PLACEHOLDER,
|
||||
)
|
||||
}
|
||||
fn has_non_region_placeholders(&self) -> bool {
|
||||
self.has_type_flags(TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER)
|
||||
}
|
||||
fn needs_subst(&self) -> bool {
|
||||
self.has_type_flags(TypeFlags::NEEDS_SUBST)
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -556,6 +556,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…
Reference in New Issue
Block a user