Zig: Proposal: make opaque type has optional size

Created on 8 Oct 2020  路  9Comments  路  Source: ziglang/zig

make it possible to wrapping some handle type (but size != @sizeOf(usize))

Proposal syntax:

// from quickjs
const JsAtom = opaque(u32) {}; // always 32bit

it should behavior similar to enum(u32) { _ }; but won't abuse the type system.

Most helpful comment

This concept is very similar to a lot of proposals discussed in #1595

All 9 comments

This concept is very similar to a lot of proposals discussed in #1595

But my proposal will not introduce new keywords, and its focus is also different. This proposal only focuses on opaque types of specific sizes, so only numeric types can be enclosed in parentheses.

I think an opaque type "of a specific size" is no longer an opaque type.

@codehz i don't think it's a good idea, especially backing a opaque type with a size will defeat it's original idea of being opaque. Using an integer type will also give its backing store semantics, which isn't ideal as well (as people can and will @bitCast it then).

I think the use case for handles is completly solved with exhaustive enums and isn't a hack at all.

If you need a type that has a size, but unknown content, you can always use extern struct { _opaque: [N]u8 } which isn't really introspectible as well and is "just memory"

@MasterQ32 in fact I want a replacement for const handle = extern enum (u16) { _ } and const handle = u16
The problem with the extern struct is that it may have some special abi rule for struct(in c), like require caller provide buffer(in some c abi)
see https://godbolt.org/z/s99or3

in fact I want a replacement for const handle = extern enum (u16) { _ } and const handle = u16

But why replace something that is already perfectly fine?

The problem with the extern struct is that it may have some special abi rule for struct(in c), like require caller provide buffer(in some c abi)

The same ABI rules will apply to a type that is not known if it is struct or integer ;) A opaque type doesn't convey any information except that it has an address. As soon as you define it as either enum or struct (which is your proposal), you enforce ABI mapping and the same problems arise with either struct or enum ABI

@MasterQ32

  1. extern enum (u16) { _ } is abusing the type system. because it is actually not an enumeration.
  2. const handle = u16 cannot define custom function on it(that's why original opaque proposal was made).
  3. distinct type (if approved) will inherit some behaviors from original type, it is not intended, we do not want to perform arithmetic operations on the handle type.

The same ABI rule

no, extern enum should act as a number in any abi, but struct won't, see godbolt.org/z/s99or3

A opaque type doesn't convey any information except that it has an address

not actually, if you look at the HWND type(and many other windows type), you will find that it is not actually a real pointer, it just a handle that has machine word length(so it is not an address, we just abuse type system again).

so why not extended it to non-machine word type?

we will have two types of opaque type for ffi, one is machine word length (pointer to non-sized opaque), the other is not necessarily machine word length (sized opaque)

Maybe it can be combined into one, make opaque to a machine word length size type, but can be changed to another length.

extern enum (u16) { _ } is abusing the type system. because it is actually not an enumeration.

I don't think so. A handle type is just an enumeration of all possible handle values. Each of them is distinct and can only be equality-compared to other handle values, especially to invalid ones:

const Handle = extern enum (u16) {
    invalid = 0,
    _
};

extern fn createObject() Handle;

var obj = createObject();
if(obj == .invalid)
    return error.InvalidHandle;

There are even better examples out there, for example WinAPI uses handles and several special values that inform the user of different things, like invalid, current and a explicit handle.

You cannot even model these kind of handles with an opaque type (as you have no control over its memory layout)

@MasterQ32 in fact I want a replacement for const handle = extern enum (u16) { _ } and const handle = u16
The problem with the extern struct is that it may have some special abi rule for struct(in c), like require caller provide buffer(in some c abi)
see https://godbolt.org/z/s99or3

This is also a perfect example why your proposal isn't working out. Integers/Enumerations are not structs, but an opaque type doesn't have information how it is represented in memory. They can be pointers, handles, whatever. You are only allowed to have a pointer to them, the only information you have is "that thing has an address and i can use that as its identity."

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jorangreef picture jorangreef  路  3Comments

andersfr picture andersfr  路  3Comments

jayschwa picture jayschwa  路  3Comments

bheads picture bheads  路  3Comments

S0urc3C0de picture S0urc3C0de  路  3Comments