Skip to content

ability to create primitive types from TypeInfo, but not necessarily aggregate types #2907

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
andrewrk opened this issue Jul 16, 2019 · 11 comments
Labels
accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@andrewrk
Copy link
Member

We have the @reify proposal here: #383. One of the reasons it's not accepted yet is that it's big and scary and has some pretty serious implications for how complicated zig code is allowed to be.

This is a proposal which is a subset of #383 with a smaller scope, which is a builtin function (and I'm going to suggest a different name here) @Type which turns builtin.TypeInfo into a type. In this proposal, if you try to make a struct, you get a compile error "unable to create struct type". The list of supported types would be:

  • Void
  • Bool
  • NoReturn
  • Int (this would replace @IntType)
  • Float
  • Pointer
  • Array
  • ComptimeFloat
  • ComptimeInt
  • Undefined
  • Null
  • Optional
  • ErrorUnion
  • ErrorSet
  • Opaque (this would replace @OpaqueType)
  • Promise
  • Vector (this would replace @Vector)

This issue is a prerequisite to #383.

@andrewrk andrewrk added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Jul 16, 2019
@andrewrk andrewrk added this to the 0.5.0 milestone Jul 16, 2019
@Sahnvour
Copy link
Contributor

In this proposal, if you try to make a struct, you get a compile error "unable to create struct type"

Could this be conveyed by another name that @Type, like @BuiltinType but more well-thought ?

@marler8997
Copy link
Contributor

marler8997 commented Jul 16, 2019

Bikeshedding Disclaimer

@InfoType could work as it's the reverse of @typeInfo and it's the functional inverse of it. Of course @Type is nice and short so I would only suggest a longer name if there were potential name conflicts with @Type.

@thejoshwolfe
Copy link
Contributor

We can categorize types by whether their type info contains a bounded amount of information, and whether they refer to another type. An error set's type info contains a slice of possible errors, so that's an unbounded amount of information. An optional type contains another type, so that's a recursive type.

The list of types is taken from the docs on @typeInfo

Type Unbounded Recursive
Type
Void
Bool
NoReturn
Int
Float
Pointer ✔️
Array ✔️
Struct ✔️ ✔️
ComptimeFloat
ComptimeInt
Undefined
Null
Optional ✔️
ErrorUnion ✔️
ErrorSet ✔️
Enum[1] ✔️
Union[2] ✔️ ✔️
Fn ✔️ ✔️
BoundFn ✔️ ✔️
ArgTuple[3] ✔️ ✔️
Opaque
Promise ✔️
Vector ✔️
EnumLiteral[4]

[1] I'm not counting the decls here. I'm not even sure why enum's are allowed to have decls. And maybe all decls should be moved out of TypeInfo, since they're not relevant to any instance of the type. The rest of this discussion will assume that TypeInfo does not include decls.

[2] The in-memory space used by a union is bounded, but the type info is effectively the same as a struct's type info.

[3] I'm pretty sure ArgTuple should have []type instead of void type info.

[4] EnumLiteral might store the identifier characters, which is kinda unbounded,
but that doesn't seem significant to this discussion.

This proposal seems to be attempting to exclude the ✔️ ✔️ cases, which means we're missing Type, Enum, and EnumLiteral.

The term "primitive type" to me means types that are bounded and non-recursive. This includes the types you can express with a single keyword in zig (void, u32, comptime_float, noreturn, etc.). There are also some singleton types whose value is a keyword and whose type can be expressed with @typeOf() (undefined, null).

My definition of primitive types also includes Opaque types, which are quite the special case. The OP comment "(this would replace @OpaqueType)" suggests that @Type(.Opaque) is how you would create an opaque type, making opaque types an exception to @Type(@typeInfo(T)) == T. This seems a little strange.

I think there's a good argument to be able to construct pointer types with some builtin function, because pointer types have so much metadata (const, align(N), etc.). While there is not a good reason to support creating optional types (since you could just ?@Type(T),), it makes more sense if we already want to do pointer types. Then we should do all the bounded recursive types, like Array, Vector, Promise. But I think we should call it something other than "primitive types". I don't have a good name for it right now other than "bounded, possibly-recursive types" 🤷‍♂️ .

This was referenced Aug 20, 2019
@marler8997
Copy link
Contributor

marler8997 commented Aug 22, 2019

Should the @Type builtin only accept TypeInfo or should it also accept any instance of a TypeInfo sub-type? i.e. should this work?

const MyPointerType = @Type(builtin.TypeInfo.Pointer {
    .size = builtin.TypeInfo.Pointer.Size.One,
    .is_const = false,
    .is_volatile = false,
    .alignment = 1,
    .child = u8,
    .is_allowzero = false,
});

Or should we require this?

const MyPointerType = @Type(builtin.TypeInfo {
    .Pointer = builtin.TypeInfo.Pointer {
        .size = builtin.TypeInfo.Pointer.Size.One,
        .is_const = false,
        .is_volatile = false,
        .alignment = 1,
        .child = u8,
        .is_allowzero = false,
    }
);

Note that it shouldn't be much more code to implement.

@marler8997
Copy link
Contributor

Implementation here: #3111

@andrewrk andrewrk added the accepted This proposal is planned. label Sep 4, 2019
@andrewrk
Copy link
Member Author

andrewrk commented Sep 4, 2019

This is mostly done thanks to @marler8997. The types left to implement are:

  • Array
  • Optional
  • ErrorUnion
  • ErrorSet
  • Enum
  • Opaque
  • FnFrame
  • AnyFrame
  • Vector
  • EnumLiteral

@tadeokondrak

This comment has been minimized.

@SpexGuy
Copy link
Contributor

SpexGuy commented May 5, 2020

I'm not certain that we should allow @Type to construct enums. Constructing anything that declares an identifier from a comptime string would make "go to definition" and autocomplete features of an editor extremely difficult to implement (would have to embed an entire comptime VM that works on half-written code), and would mean it's impossible to know you'll be able to grep for the definition of an enum literal (or, soon after, struct field). If you need to write an api that dynamically creates comptime-known values with names that are comptime-known strings, it can be done by exposing a function fn getValue(comptime name: []const u8) GenType, or with code generation. So this rule doesn't limit comptime functionality.

@tadeokondrak
Copy link
Contributor

Constructing anything that declares an identifier from a comptime string would make "go to definition" and autocomplete features of an editor extremely difficult to implement (would have to embed an entire comptime VM that works on half-written code)

I think this is already true, you can do something like

fn SomeType() type {
    return if (comptime function())
        struct { const A = 1; const B = 2; }
    else
        struct { const A = 2; };
}

@alexnask
Copy link
Contributor

alexnask commented May 11, 2020

I agree, you basically need to be a zig compiler (or at least comptime engine) to correctly do completions etc, adding aggregate type reification does make it slightly more diffciult but not by a huge degreee.

Personally I would be okay with generating any aggregate type as long as you cannot generate functions in its namespace but I do get the arguments against it.

Having enum reification alone will aready let metaprogramming code do a lot more without introducing really surprising behavior.

@tadeokondrak
Copy link
Contributor

This is fully implemented now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

7 participants