Initial (incomplete) implementation of transmutability trait.
This initial implementation handles transmutations between types with specified layouts, except when references are involved. Co-authored-by: Igor null <m1el.2027@gmail.com>
This commit is contained in:
parent
2a220937c2
commit
bc4a1dea41
91 changed files with 5691 additions and 2 deletions
|
@ -305,6 +305,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
|
||||
} else if lang_items.destruct_trait() == Some(def_id) {
|
||||
self.assemble_const_destruct_candidates(obligation, &mut candidates);
|
||||
} else if lang_items.transmute_trait() == Some(def_id) {
|
||||
// User-defined transmutability impls are permitted.
|
||||
self.assemble_candidates_from_impls(obligation, &mut candidates);
|
||||
self.assemble_candidates_for_transmutability(obligation, &mut candidates);
|
||||
} else {
|
||||
if lang_items.clone_trait() == Some(def_id) {
|
||||
// Same builtin conditions as `Copy`, i.e., every type which has builtin support
|
||||
|
@ -873,6 +877,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
};
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self, obligation, candidates))]
|
||||
fn assemble_candidates_for_transmutability(
|
||||
&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
candidates: &mut SelectionCandidateSet<'tcx>,
|
||||
) {
|
||||
if obligation.has_param_types_or_consts() {
|
||||
candidates.ambiguous = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if obligation.has_infer_types_or_consts() {
|
||||
candidates.ambiguous = true;
|
||||
return;
|
||||
}
|
||||
|
||||
candidates.vec.push(TransmutabilityCandidate);
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self, obligation, candidates))]
|
||||
fn assemble_candidates_for_trait_alias(
|
||||
&mut self,
|
||||
|
|
|
@ -48,6 +48,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
ImplSource::Builtin(data)
|
||||
}
|
||||
|
||||
TransmutabilityCandidate => {
|
||||
let data = self.confirm_transmutability_candidate(obligation)?;
|
||||
ImplSource::Builtin(data)
|
||||
}
|
||||
|
||||
ParamCandidate(param) => {
|
||||
let obligations =
|
||||
self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref));
|
||||
|
@ -267,6 +272,53 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
ImplSourceBuiltinData { nested: obligations }
|
||||
}
|
||||
|
||||
fn confirm_transmutability_candidate(
|
||||
&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
) -> Result<ImplSourceBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
|
||||
debug!(?obligation, "confirm_transmutability_candidate");
|
||||
|
||||
let predicate = obligation.predicate;
|
||||
|
||||
let type_at = |i| predicate.map_bound(|p| p.trait_ref.substs.type_at(i));
|
||||
let bool_at = |i| {
|
||||
predicate
|
||||
.skip_binder()
|
||||
.trait_ref
|
||||
.substs
|
||||
.const_at(i)
|
||||
.try_eval_bool(self.tcx(), obligation.param_env)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let src_and_dst = predicate.map_bound(|p| rustc_transmute::Types {
|
||||
src: p.trait_ref.substs.type_at(1),
|
||||
dst: p.trait_ref.substs.type_at(0),
|
||||
});
|
||||
|
||||
let scope = type_at(2).skip_binder();
|
||||
|
||||
let assume = rustc_transmute::Assume {
|
||||
alignment: bool_at(3),
|
||||
lifetimes: bool_at(4),
|
||||
validity: bool_at(5),
|
||||
visibility: bool_at(6),
|
||||
};
|
||||
|
||||
let cause = obligation.cause.clone();
|
||||
|
||||
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;
|
||||
|
||||
match maybe_transmutable {
|
||||
Answer::Yes => Ok(ImplSourceBuiltinData { nested: vec![] }),
|
||||
_ => Err(Unimplemented),
|
||||
}
|
||||
}
|
||||
|
||||
/// This handles the case where an `auto trait Foo` impl is being used.
|
||||
/// The idea is that the impl applies to `X : Foo` if the following conditions are met:
|
||||
///
|
||||
|
|
|
@ -1630,6 +1630,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
// FIXME(@jswrenn): this should probably be more sophisticated
|
||||
(TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => false,
|
||||
|
||||
// (*)
|
||||
(
|
||||
BuiltinCandidate { has_nested: false }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue