Safe Transmute: Enable handling references, including recursive types
This patch enables support for references in Safe Transmute, by generating nested obligations during trait selection. Specifically, when we call `confirm_transmutability_candidate(...)`, we now recursively traverse the `rustc_transmute::Answer` tree and create obligations for all the `Answer` variants, some of which include multiple nested `Answer`s. Also, to handle recursive types, enable support for coinduction for the Safe Transmute trait (`BikeshedIntrinsicFrom`) by adding the `#[rustc_coinduction]` annotation. Also fix some small logic issues when reducing the `or` and `and` combinations in `rustc_transmute`, so that we don't end up with additional redundant `Answer`s in the tree. Co-authored-by: Jack Wrenn <jack@wrenn.fyi>
This commit is contained in:
parent
97d328012b
commit
8f1cec8d84
26 changed files with 460 additions and 103 deletions
|
@ -30,33 +30,46 @@ impl fmt::Debug for Byte {
|
|||
}
|
||||
|
||||
pub(crate) trait Def: Debug + Hash + Eq + PartialEq + Copy + Clone {}
|
||||
pub trait Ref: Debug + Hash + Eq + PartialEq + Copy + Clone {}
|
||||
pub trait Ref: Debug + Hash + Eq + PartialEq + Copy + Clone {
|
||||
fn min_align(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn is_mutable(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl Def for ! {}
|
||||
impl Ref for ! {}
|
||||
|
||||
#[cfg(feature = "rustc")]
|
||||
pub(crate) mod rustc {
|
||||
pub mod rustc {
|
||||
use rustc_middle::mir::Mutability;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::Region;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
||||
/// A reference in the layout.
|
||||
#[derive(Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Clone, Copy)]
|
||||
pub struct Ref<'tcx> {
|
||||
lifetime: Region<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
mutability: Mutability,
|
||||
pub lifetime: ty::Region<'tcx>,
|
||||
pub ty: Ty<'tcx>,
|
||||
pub mutability: Mutability,
|
||||
pub align: usize,
|
||||
}
|
||||
|
||||
impl<'tcx> super::Ref for Ref<'tcx> {}
|
||||
impl<'tcx> super::Ref for Ref<'tcx> {
|
||||
fn min_align(&self) -> usize {
|
||||
self.align
|
||||
}
|
||||
|
||||
impl<'tcx> Ref<'tcx> {
|
||||
pub fn min_align(&self) -> usize {
|
||||
todo!()
|
||||
fn is_mutable(&self) -> bool {
|
||||
match self.mutability {
|
||||
Mutability::Mut => true,
|
||||
Mutability::Not => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'tcx> Ref<'tcx> {}
|
||||
|
||||
/// A visibility node in the layout.
|
||||
#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
|
||||
|
|
|
@ -365,6 +365,17 @@ pub(crate) mod rustc {
|
|||
}
|
||||
}))
|
||||
}
|
||||
|
||||
ty::Ref(lifetime, ty, mutability) => {
|
||||
let align = layout_of(tcx, *ty)?.align();
|
||||
Ok(Tree::Ref(Ref {
|
||||
lifetime: *lifetime,
|
||||
ty: *ty,
|
||||
mutability: *mutability,
|
||||
align,
|
||||
}))
|
||||
}
|
||||
|
||||
_ => Err(Err::Unspecified),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue