# Is \`(unsafe-struct\*-ref s -1)\` a stable way to get type descriptors in Racket?

**URL:** <https://racket.discourse.group/t/is-unsafe-struct-ref-s-1-a-stable-way-to-get-type-descriptors-in-racket/1646>\
**Category:** Questions & Answers\
**Created:** [January 19, 2023, 4:12am UTC](https://racket.discourse.group/t/is-unsafe-struct-ref-s-1-a-stable-way-to-get-type-descriptors-in-racket/1646 "2023-01-19T04:12:47Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![MartianMoorGrove](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/martianmoorgrove/32/965_2.png) [@MartianMoorGrove](https://racket.discourse.group/u/MartianMoorGrove)\
**Post date:** [January 19, 2023, 4:12am UTC](https://racket.discourse.group/t/is-unsafe-struct-ref-s-1-a-stable-way-to-get-type-descriptors-in-racket/1646/1 "2023-01-19T04:12:47Z")

</div>

By stable I mean that the location of struct type descriptors within struct instances is, within reason, a permanent feature of the language.

Obviously on it's own that code is both unsafe and useless on impersonators, but it is a lot faster than using the `struct-info` procedure and if it's stable I could implement a different kind of struct type properties that may be more suited to one of my projects.

Just to clarify, I'm using Racket CS. It may be that the code doesn't work with Racket BC.

---

<div class="post-metadata">

**Author:** ![gus-massa](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/gus-massa/32/507_2.png) [@gus-massa](https://racket.discourse.group/u/gus-massa)\
**Post date:** [January 19, 2023, 2:56pm UTC](https://racket.discourse.group/t/is-unsafe-struct-ref-s-1-a-stable-way-to-get-type-descriptors-in-racket/1646/2 "2023-01-19T14:56:29Z")

</div>

I'm not sure about the implementation details. Do you get the same result or just an opaque value that is good enough for what you need? Does that bypass the `current-inspector`?

I'm worried than in the future some internal part of the compiler like `cptypes` may be smart enough to detect that `-1` is wrong and assume that the operation will raise an error of have an undefined behavior and then make an unpredictable optimization (like cutting all the code that follows it).

(My guess is that `unsafe-struct*-ref` is currently not expanded to Chez Scheme code, so the optimizations can't see the problem. But this kind of implementation details may change in the future.)

@mflatt: Does it make sense to add something like `struct-info*` to fix the problem?

---

<div class="post-metadata">

**Author:** ![MartianMoorGrove](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/martianmoorgrove/32/965_2.png) [@MartianMoorGrove](https://racket.discourse.group/u/MartianMoorGrove)\
**Post date:** [January 19, 2023, 6:36pm UTC](https://racket.discourse.group/t/is-unsafe-struct-ref-s-1-a-stable-way-to-get-type-descriptors-in-racket/1646/3 "2023-01-19T18:36:38Z")

</div>

It returns a result `eq?` to the struct type descriptor defined by the relevant struct form outside of the code, which is what I need.  
It accesses the `-1` index as fast as any other index, so I assume it does bypass the `current-inspector`. In my case that should be okay, as struct instances would have to first pass a type check: anything that doesn't satisfy the check would not have it's opacity breached.

I'm just exploring some options for implementing my class library. Being able to manually implement my own struct type properties using the code in question could give a large speed boost to dynamic dispatch of methods.

---

<div class="post-metadata">

**Author:** ![mflatt](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/mflatt/32/6_2.png) [@mflatt](https://racket.discourse.group/u/mflatt)\
**Post date:** [January 19, 2023, 10:13pm UTC](https://racket.discourse.group/t/is-unsafe-struct-ref-s-1-a-stable-way-to-get-type-descriptors-in-racket/1646/4 "2023-01-19T22:13:53Z")

</div>

An `unsafe-struct*-ref` call is inlined as `$record-ref` at the Chez Scheme level, which means that the `cptypes` possibility is relevant.

Adding `unsafe-struct*-type` would make sense, and that seems like the right thing to do. An unsafe operation more like `struct-info` does not seem as useful, since determining whether the structure type is transparent is probably too much overhead.

(An `unsafe-struct*-type` would be inlined as `$record-type-descriptor`. So, another option to get the same functionality is to use `ffi/unsafe/vm` to get `$record-type-descriptor`, and then call that on the structure. But since the operation would not be inlined, that's probably not useful here.)

---

<div class="post-metadata">

**Author:** ![MartianMoorGrove](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/martianmoorgrove/32/965_2.png) [@MartianMoorGrove](https://racket.discourse.group/u/MartianMoorGrove)\
**Post date:** [January 20, 2023, 12:10am UTC](https://racket.discourse.group/t/is-unsafe-struct-ref-s-1-a-stable-way-to-get-type-descriptors-in-racket/1646/5 "2023-01-20T00:10:21Z")

</div>

If `unsafe-struct*-type` would be at least 85% as fast as using `unsafe-struct*-ref` then I think it would be worth it for a custom struct type properties implementation. It may be worth adding for other reasons.

Otherwise, I'm satisfied that using `(unsafe-struct*-ref s -1)` is not a stable option for extracting type descriptors. I'll explore other options for now. Thanks to both you and @gus-massa for the discussion!

---

<div class="post-metadata">

**Author:** ![mflatt](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/mflatt/32/6_2.png) [@mflatt](https://racket.discourse.group/u/mflatt)\
**Post date:** [January 20, 2023, 12:32am UTC](https://racket.discourse.group/t/is-unsafe-struct-ref-s-1-a-stable-way-to-get-type-descriptors-in-racket/1646/6 "2023-01-20T00:32:56Z")

</div>

Yes, `(unsafe-struct*-type s)` would generate the same machine code that `(unsafe-struct*-ref s -1)` currently does. I'll plan to add it soon, pending further discussion here. Meanwhile, you could rely on `(unsafe-struct*-ref s -1)` working until `unsafe-struct*-type` is added.

---

<div class="post-metadata">

**Author:** ![MartianMoorGrove](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/martianmoorgrove/32/965_2.png) [@MartianMoorGrove](https://racket.discourse.group/u/MartianMoorGrove)\
**Post date:** [January 20, 2023, 12:59am UTC](https://racket.discourse.group/t/is-unsafe-struct-ref-s-1-a-stable-way-to-get-type-descriptors-in-racket/1646/7 "2023-01-20T00:59:37Z")

</div>

Oh awesome. I'll go ahead and use it for now.
