Skip to content

valtrees and padding #20

Open
Open
@lcnr

Description

@lcnr

we intend to transition const generics over to valtrees, this representation erases padding bytes.

We also intend to allow the following example to compile:

const fn some_operation::<const N: usize>() -> usize { N }
const fn other_operation(x: usize) -> usize { x + 1 }

fn outer<const N: usize>() -> [u8; other_operation(some_operation::<N>())] {
    inner::<{ some_operation::<N>() }>()
}
fn inner<const M: usize>() -> [u8; other_operation(M)] {
    [u0; other_operation(M)]
}

for this to compile, we have to unify the constant other_operation(some_operation::<N>()) with the constant other_operation(M) using the generic argument some_operation::<N>() as argument for M. This is sound as long as const eval doesn't have side effects.

A concern is the interaction between padding bytes and valtrees. We intend to not remember padding bytes in constants used in the type system, but do remember them during const eval and can soundly get their value (afaik). This means that putting values into the type system in the middle of const eval can have observable effects, e.g. consider

#![feature(generic_const_exprs, adt_const_params)]

#[repr(C)]
#[derive(PartialEq, Eq)]
struct Foo {
    v1: u8,
    // _padding: u8,
    v2: u16,
}

#[repr(C)]
struct FooWithPadding {
    v1: u8,
    padding: u8,
    v2: u16,
}

const fn with_valid_padding<const N: u32>() -> &'static Foo {
    unsafe {
        &*(&N as *const u32).cast::<Foo>()
    }
}

const fn reads_padding(v: &'static Foo) -> usize {
    unsafe {
        &*(v as *const Foo).cast::<FooWithPadding>()
    }.padding as usize
}

fn direct_use<const N: u32>() -> [u8; reads_padding(with_valid_padding::<N>())] {
    generic_reads_padding::<{ with_valid_padding::<N>() }>()
}

fn generic_reads_padding<const FOO: &'static Foo>() -> [u8; reads_padding(FOO)] {
    [0; reads_padding(FOO)]
}

fn main() {
    println!("{:x}", direct_use::<0x0000bb00>().len());
}

direct_use must not compile with valtrees as the behavior of reads_padding differs between the two constants.

cc @RalfJung @oli-obk

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions