Skip to content

Layout guarantee information draft#1325

Draft
firefighterduck wants to merge 10 commits into
AeneasVerif:mainfrom
firefighterduck:symbolic_layout
Draft

Layout guarantee information draft#1325
firefighterduck wants to merge 10 commits into
AeneasVerif:mainfrom
firefighterduck:symbolic_layout

Conversation

@firefighterduck

@firefighterduck firefighterduck commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

This PR is a first draft of how Charon could support (partially) symbolic layout guarantee information. To make the draft more self-contained and easier to review, all relevant parts are in the new file charon/src/ast/layout_guarantees.rs. Additional changes required for this PR can be found in other files, some of which should and probably will be extracted into their own PRs.

About layout guarantees

Layout guarantees are (partially symbolic) expressions that describe what Rust guarantees about the layout of a type. I've tried to always refer to the reference in the code to keep everything in sync. In general, these guarantees can be computed for polymorphic types and are target-agnostic, but can be concretized/instantiated for specific type arguments and targets if needed (currently only implemented in Rust, not in OCaml).

The draft is insofar complete as it can compute layout guarantees for most types (an open question are DSTs). Further open points for future discussion are the following:

  • Can we compute symbolic layout guarantees about more type properties, e.g. whether a type is uninhabited (based on some symbolic predicates)? Optimally, we'd be able to represent all fields of SizedTypeProperties, but symbolically.
  • One ui test currently fails, but I was not able to figure out what exactly goes wrong and how to fix it. The problem now gets circumvented.
  • Does this already satisfy all requirements by all stakeholders (compare with Zulip thread where we collected them)?

Comment thread charon/src/ast/types.rs Outdated
Comment on lines +534 to +535
Serialize,
Deserialize,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove these two whenever there's also De/SerializeState

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Funny thing, I believe at least ItemId requires both. It needs to be stateful to work in TranslatedCrate::item_names, but needs to be stateless for use in DeclarationGroup.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, this is hitting a limitation of serde_state I should fix :/ It's just that it doesn't support mixing stateless and using a custom serialization function.

Comment thread charon/src/ast/layout_guarantees.rs Outdated
/// The basic building blocks of symbolic layout information.
#[derive(Debug, Clone, PartialEq, Eq, SerializeState, DeserializeState, Drive, DriveMut)]
#[serde_state(state_implements = HashConsSerializerState)]
pub enum LayoutGuaranteeAtom {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this always represent a symbolic number of bits?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It represents a number of bytes, but yes, its always a symbolic of concrete number of bytes. For some types, knowing the target suffices to know the number of bytes, but since the type could also be a DST, it might still be an indeterminable number.

Comment thread charon/src/ast/krate.rs Outdated
/// Stores the exact alignments for most primitive types.
#[derive(Clone, Drive, DriveMut, Serialize, Deserialize)]
pub struct TargetAlignments {
pub i1_align: types::ByteCount,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the i1 for?

@firefighterduck firefighterduck Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question. Rustc has it, LLVM has it, and so I simply kept it. I currently use it for the alignment of booleans, bu I don't know whether that's correct.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That isn't correct, booleans are aligned like u8. Looking through rustc, it's indeed used to align 1-bit integers, I just have no idea how one may come about

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove it until we have a use for it

Comment on lines +446 to +451
/// A structure that computes and stores originally symbolic layouts, which have been
/// concretized as much as possible. Will not be used during translation.
pub struct Concretizer {
computed_layouts: SeqHashMap<Ty, LayoutGuarantees>,
curr_requested: HashSet<Ty>,
}

@Nadrieril Nadrieril Jul 15, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's "concretized"? Is this just "normalized"? The API I'd imagine for that would be:

pub struct LayoutComputer<'a> {
  krate: &'a TranslatedCrate,
  target: TargetTriple,
  cache: HashMap<Ty, LayoutGuarantee>,
  /// Stack to bail on cycles in the computation.
  stack: Vec<Ty>,
}
impl LayoutComputer<'a> {
    pub fn new(krate: &'a TranslatedCrate, target: Option<TargetTriple>) -> Self { ... }
    /// Computes the most precise layout guarantees we can deduce for this type.
    pub fn compute_layout(&self, ty: Ty) -> LayoutGuarantees { ... }
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to bikeshedding the name. For me, it concretizes the layout guarantees, since it inserts concrete values where possible. Normalizing for me could also mean just rearranging the purely symbolic expressions.

Your API looks nice and I'll use it as the basis for further iterations.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normalizing for me could also mean just rearranging the purely symbolic expressions.

Well yeah, that's what it has to do in cases where fully concrete cannot be obtained, e.g. for any repr(Rust) layout

Comment thread charon/src/bin/charon-driver/translate/translate_types.rs Outdated

/// Composite symbolic layout expressions.
///
/// `non_exhaustive` since we might need many more composite layouts.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You didn't actually make it non_exaustive

Comment thread charon/src/ast/krate.rs
Comment on lines +196 to +209
#[derive(Clone, Drive, DriveMut, Serialize, Deserialize)]
pub struct TargetAlignments {
pub i1_align: types::ConcreteByteCount,
pub i8_align: types::ConcreteByteCount,
pub i16_align: types::ConcreteByteCount,
pub i32_align: types::ConcreteByteCount,
pub i64_align: types::ConcreteByteCount,
pub i128_align: types::ConcreteByteCount,
pub f16_align: types::ConcreteByteCount,
pub f32_align: types::ConcreteByteCount,
pub f64_align: types::ConcreteByteCount,
pub f128_align: types::ConcreteByteCount,
pub ptr_align: types::ConcreteByteCount,
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just make this a map from LiteralType to ConcreteByteCount? seems more exhaustive

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would certainly be an option, if we can make it a cheap map. The current version is really just a direct translation of what rustc has.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it seems more usable as a map (just use a SeqHashMap, we're not optimizing for speed in our representation)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants