Skip to content

Containing transmutes on slices and other representations. #6790

Closed
@Kimundi

Description

@Kimundi

Right now a few places in the code base make assumptions about the internal representations of things like &[T] or other types that stand for internal representation details, mostly to implement low-level operations in unsafe blocks. For example you could see code like this:

pub fn my_slice<'r,T>(v: &'r [T], start: uint, end: uint) -> &'r [T] {
    assert!(start <= end);
    assert!(end <= v.len());
    unsafe {
        let mut (buf, len): (*T, uint) = transmute(v);
        buf += start;
        len = end - start;
        transmute(buf, len)
    }
}

This is fine as long as the internal representation of those things doesn't change, but will wreak random havoc if something changes (for example as result of the implementation of the Dynamic types proposal, or a change to the way &str handles its hidden trailing byte)

To improve on this situation, I think the following needs to be done for all build-in 'special' types like &[T], &str, char etc:

  • Have a central place in std::unstable for the underlying representation. It would contain things like struct SliceRep<T> { buf: *T, len:uint } or struct CharRep { v: uint }.
  • Have functions to safely cast a type to its repr, to unsafely cast a repr to its type, and if possible functions to safely cast a repr to it's type provided all necessary invariants are unviolated.
  • Implement a lint warning for calls of transmute-like functions from/to those types. All low level work and casts to representations would then have to happen through the functions in the corresponding modules, where the warnings get explicitly disabled with an attribute.

The canonical warn-free way to write my_slice would then become something like this:

pub fn my_slice<'r,T>(v: &'r [T], start: uint, end: uint) -> &'r [T] {
    assert!(start <= end);
    assert!(end <= v.len());
    let mut repr = v.to_internal_repr();
    unsafe {
        repr.buf += start;
        repr.len = end - start;
        repr.to_type()
    }
}

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