# Pre-RFC: PhantomUnsized and thin pointers

**URL:** https://internals.rust-lang.org/t/pre-rfc-phantomunsized-and-thin-pointers/10659
**Category:** Uncategorized
**Created:** [August 2, 2019, 10:42pm UTC](https://internals.rust-lang.org/t/pre-rfc-phantomunsized-and-thin-pointers/10659 "2019-08-02T22:42:32Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)
#### Post date: [August 2, 2019, 10:42pm UTC](https://internals.rust-lang.org/t/pre-rfc-phantomunsized-and-thin-pointers/10659/1 "2019-08-02T22:42:32Z")

</div>

This is very unbaked.

TL;DR: add `std::marker::PhantomUnsized`, an "unsized ZST" marker type.

This allows for custom thin pointers to data. For example:

```rust
struct CStr {
    raw: c_char,
    unsize: PhantomUnsized,
} // and CStr things

struct Utf8Codepoint {
    raw: u8,
    unsize: PhantomUnsized,
}

impl Deref for Utf8Codepoint {
    type Target = str;
    fn deref(&self) -> &str {
        let len = utf8_length(self.raw);
        let slice = slice::from_raw_parts(&self.raw, len);
        str::from_utf8_unchecked(slice)
    }
}

impl Utf8Codepoint {
    fn as_char(&self) -> char {
        self.chars()
            .nth(0)
            .unwrap_or_else(|| unsafe { debug_unreachable!() })
    }
}

```

## How is this different from `extern type`?

I'm not really certain. Mostly, I see it as the difference between `extern type` being the `void` in `void*` (i.e. "something I know nothing about") and `PhantomUnsized` being for things like turning `*const [T]` into `*const (T, PhantomUnsized)` where it is more cleanly "`*const T` but unsized". Also, `PhantomUnsized` is a smaller change that could be pushed through quickly (in theory).

[I currently have a `struct Character { raw: str }` in [windex](https://github.com/cad97/windex), but have been considering if making `&Character` a thin pointer would be better. Probably not, thinking about it after writing this, but `PhantomUnsized` is still an interesting minimal addition.]

---

<div class="post-metadata">

### Author: ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)
#### Post date: [August 2, 2019, 10:52pm UTC](https://internals.rust-lang.org/t/pre-rfc-phantomunsized-and-thin-pointers/10659/2 "2019-08-02T22:52:27Z")

</div>

I think it would be better if [Custom DSTs](https://github.com/rust-lang/rfcs/pull/2594) were introduced into the language because this can only handle the case where there is no meta-data (thin pointers). But this may have its uses as a short term solution.

---

<div class="post-metadata">

### Author: ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)
#### Post date: [August 3, 2019, 4:01am UTC](https://internals.rust-lang.org/t/pre-rfc-phantomunsized-and-thin-pointers/10659/3 "2019-08-03T04:01:40Z")

</div>

As far as fat pointers go, I really liked the idea to support const generic erasure.

e.g. you have `&MatrixSlice<4, 4>` for a 4x4 matrix, and `&MatrixSlice<dyn, dyn>` for a matrix where the dimension data is "hoisted" from static to the fat pointer metadata. (So `[T]` is `[T; dyn]`.)

Ignoring syntax issues for now (the time I saw this suggestion, it was brought up that e.g. `&&[T; dyn]` is ambiguous to which reference should be fat), are there DST use cases that wouldn't be covered by one of these?

I _think_ `extern type`, `PhantomUnsized`, and "`dyn const`" cover the three types of custom DST (unknowable, inline/thin, and fat, respectively). And each of these is (in theory) fairly simple, in comparison to the full-fledged custom DSTs.

---

<div class="post-metadata">

### Author: ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)
#### Post date: [August 3, 2019, 7:47am UTC](https://internals.rust-lang.org/t/pre-rfc-phantomunsized-and-thin-pointers/10659/4 "2019-08-03T07:47:30Z")

</div>

I wouldn't call `dyn const` simple, its semantics can be confusing and rather arbitratry. I would not like to see that even if we never get Custom DSTs in any other form.

---

<div class="post-metadata">

### Author: ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)
#### Post date: [August 3, 2019, 9:14am UTC](https://internals.rust-lang.org/t/pre-rfc-phantomunsized-and-thin-pointers/10659/5 "2019-08-03T09:14:21Z")

</div>

> [@CAD97](#):
>
> ```rust
> struct CStr {
> raw: c_char,
> unsize: PhantomUnsized,
> } // and CStr things
> 
> ```

So this type is unsized but it also has size "at least 1" (similar to e.g. `(c_char, [c_char])`. Does that mean if we apply our rules for references being dereferencable etc., that an `&CStr` must point to at least 1 byte of valid memory? That the compiler is allowed to insert spurious loads of that bytes? That it is UB to mutate that byte because it is pointed-to by a shared reference?

---

<div class="post-metadata">

### Author: ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)
#### Post date: [August 5, 2019, 2:45am UTC](https://internals.rust-lang.org/t/pre-rfc-phantomunsized-and-thin-pointers/10659/6 "2019-08-05T02:45:14Z")

</div>

I think all of that is the right semantics. (It's looser than the current fat pointer `CStr` as well.)

And that I'm thinking about it now, `([T; 0], PhantomUnsized)` would be an interesting translation for VLA. It basically says the same thing as the VLA "trick" in C: align this to `T`, may contain data after the "main" sized part of the struct that you have to handle unsafely.

For the most part, I think the obvious semantics of "make this `?Sized`, use `unsafe` to track whatever data is in the unsized portion" works correctly, which is why I think this is a fairly minimal addition.

---

<div class="post-metadata">

### Author: ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)
#### Post date: [November 3, 2019, 2:54am UTC](https://internals.rust-lang.org/t/pre-rfc-phantomunsized-and-thin-pointers/10659/7 "2019-11-03T02:54:52Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
