1
Fork 0

Safe Transmute: Update definition of Condition type

- Change `Condition` to not contain `Answer`s but instead just contain other
  `Condition`s directly.
- Also improve error reporting for `DstHasStricterAlignment`
This commit is contained in:
Bryan Garza 2023-05-24 17:47:13 -07:00
parent 6266358237
commit d2164d5c9a
5 changed files with 39 additions and 33 deletions

View file

@ -2751,8 +2751,7 @@ 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): Is this enough, or should we resolve all nested
// obligations like we do for `confirm_transmutability_candidate(...)?`
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
obligation.cause,
src_and_dst,
@ -2784,10 +2783,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
rustc_transmute::Reason::DstIsTooBig => {
format!("The size of `{src}` is smaller than the size of `{dst}`")
}
// FIXME(bryangarza): Say exactly what the minimum alignments of src and dst are
rustc_transmute::Reason::DstHasStricterAlignment => {
rustc_transmute::Reason::DstHasStricterAlignment {
src_min_align,
dst_min_align,
} => {
format!(
"The minimum alignment of `{src}` should be greater than that of `{dst}`, but it is not"
"The minimum alignment of `{src}` ({src_min_align}) should be greater than that of `{dst}` ({dst_min_align})"
)
}
rustc_transmute::Reason::DstIsMoreUnique => {

View file

@ -290,25 +290,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
tcx: TyCtxt<'tcx>,
obligation: &TraitObligation<'tcx>,
predicate: TraitPredicate<'tcx>,
answer: rustc_transmute::Answer<rustc_transmute::layout::rustc::Ref<'tcx>>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
answer: rustc_transmute::Condition<rustc_transmute::layout::rustc::Ref<'tcx>>,
) -> Vec<PredicateObligation<'tcx>> {
match answer {
Ok(None) => Ok(vec![]),
Err(_) => Err(Unimplemented),
// FIXME(bryangarza): Add separate `IfAny` case, instead of treating as `IfAll`
// Not possible until the trait solver supports disjunctions of obligations
Ok(Some(rustc_transmute::Condition::IfAll(answers)))
| Ok(Some(rustc_transmute::Condition::IfAny(answers))) => {
rustc_transmute::Condition::IfAll(answers)
| rustc_transmute::Condition::IfAny(answers) => {
let mut nested = vec![];
for flattened in answers
.into_iter()
.map(|answer| flatten_answer_tree(tcx, obligation, predicate, answer))
{
nested.extend(flattened?);
nested.extend(flattened);
}
Ok(nested)
nested
}
Ok(Some(rustc_transmute::Condition::IfTransmutable { src, dst })) => {
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);
@ -339,7 +337,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if dst.mutability == Mutability::Mut {
obligations.push(make_obl(dst.ty, src.ty));
}
Ok(obligations)
obligations
}
}
}
@ -371,8 +369,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
assume,
);
let fully_flattened =
flatten_answer_tree(self.tcx(), obligation, predicate, maybe_transmutable)?;
let fully_flattened = match maybe_transmutable {
Err(_) => Err(Unimplemented)?,
Ok(Some(mt)) => flatten_answer_tree(self.tcx(), obligation, predicate, mt),
Ok(None) => vec![],
};
debug!(?fully_flattened);
Ok(ImplSourceBuiltinData { nested: fully_flattened })
}