Skip to content
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

std: remove meta.trait #18061

Merged
merged 1 commit into from
Nov 22, 2023
Merged

std: remove meta.trait #18061

merged 1 commit into from
Nov 22, 2023

Conversation

andrewrk
Copy link
Member

In general, I don't like the idea of std.meta.trait, and so I am providing some guidance by deleting the entire namespace from the standard library and compiler codebase.

My main criticism is that it's overcomplicated machinery that bloats compile times and is ultimately unnecessary given the existence of Zig's strong type system and reference traces.

Users who want this can create a third party package that provides this functionality.

closes #18051

@andrewrk andrewrk enabled auto-merge (rebase) November 21, 2023 22:36
@andrewrk andrewrk added breaking Implementing this issue could cause existing code to no longer compile or have different behavior. standard library This issue involves writing Zig code for the standard library. labels Nov 21, 2023
@nektro
Copy link
Contributor

nektro commented Nov 21, 2023

std.meta.trait.isZigString should be moved into the main std.meta namespace then, as this is an instrumentally useful function

Copy link
Contributor

@dweiller dweiller left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are a few places where old checks should be rewritten rather than removed.

In addition to those below, it might also be worth rewriting the checks in the *As*ReturnType functions in mem.zig, particularly for asBytes/AsBytesReturnType which don't do any field accesses that might help catch incorrect usage, but I'm less sure these cases.

Comment on lines -786 to -797
fn validateType(comptime T: type) void {
comptime {
if (!((std.meta.trait.isSlice(T) or
std.meta.trait.is(.Array)(T) or
std.meta.trait.isPtrTo(.Array)(T)) and
std.meta.Elem(T) == u8))
{
@compileError("expect a slice, array or pointer to array of u8, got " ++ @typeName(T));
}
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth rewriting this check in order to make the error message more helpful. For this test:

const std = @import("std");

test {
    const data = [_]u32{1, 2, 3, 4, 5, 6};
    _ = std.hash.XxHash64.hash(0, data);
}

the current compilation error without validateType is:

lib/std/hash/xxhash.zig:94:45: error: expected type '*const [4]u8', found '*const [4]u32'
                acc = finalize4(acc, partial[0..4]);
                                     ~~~~~~~^~~~~~
lib/std/hash/xxhash.zig:94:45: note: pointer type child 'u32' cannot cast into pointer type child '[4]u8'
lib/std/hash/xxhash.zig:150:33: note: parameter type declared here
    fn finalize4(v: u64, bytes: *const [4]u8) u64 {
                                ^~~~~~~~~~~~

which I think is a little opaque.

@@ -35,7 +33,6 @@ pub fn BitWriter(comptime endian: std.builtin.Endian, comptime WriterType: type)
if (bits == 0) return;

const U = @TypeOf(value);
comptime assert(trait.isUnsignedInt(U));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be replaced with comptime assert(@typeInfo(U).Int.signedness == .unsigned);. If an unsigned int is passed in without this check there is checked illegal behaviour (i.e. runtime panic in safe modes) at the @intCasts below.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thank you

@@ -315,8 +311,6 @@ pub const XxHash32 = struct {
}

pub fn update(self: *XxHash32, input: []const u8) void {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I missed changing this input parameter to anytype if you want to include that here, if not I'll make a PR for it.

@mitchellh
Copy link
Contributor

std.meta.trait.isZigString should be moved into the main std.meta namespace then, as this is an instrumentally useful function

What is this useful for? I don't mean that in a combative tone, this is a genuine question since I've never had a use for it.

@nektro
Copy link
Contributor

nektro commented Nov 22, 2023

when you're accepting a value in from an anytype and want to know if it is in the general shape of a []const u8. isZigString handles checking for slice, nul-terminated pointer, pointer-to-array, etc

@xdBronch
Copy link
Contributor

if youre allowing a function to accept both slices/array pointers and null terminated many pointers then you have to handle them differently regardless in which case using a trait function would be redundant, no?

@Jarred-Sumner
Copy link
Contributor

looks like we have about 70 usages of std.meta.trait. in Bun's codebase

image

@andrewrk
Copy link
Member Author

andrewrk commented Nov 22, 2023

It's pretty straightforward to copy those trait functions into the Bun codebase if you want to keep using them.

Looking at the screenshot, I would consider every one of those a code smell.

@expikr
Copy link
Contributor

expikr commented Nov 22, 2023

I don't disagree but optics-wise the communication could be a little more diplomatic than just "ur bad" when justifying the breaking of production code, as it sets the tone to spectators judging the community.

@andrewrk
Copy link
Member Author

Buckle up, I have even more breakages planned.

In general, I don't like the idea of std.meta.trait, and so I am
providing some guidance by deleting the entire namespace from the
standard library and compiler codebase.

My main criticism is that it's overcomplicated machinery that bloats
compile times and is ultimately unnecessary given the existence of Zig's
strong type system and reference traces.

Users who want this can create a third party package that provides this
functionality.

closes #18051
@andrewrk andrewrk merged commit d5e21a4 into master Nov 22, 2023
0 of 8 checks passed
@andrewrk andrewrk deleted the remove-std.meta.trait branch November 22, 2023 18:24
@wrongnull
Copy link
Contributor

looks like we have about 70 usages of std.meta.trait. in Bun's codebase
image

I decided to create a third party package that would retain this functionality and add new functionality depending on user needs in the future. https://github.com/wrongnull/zigtrait

Hanaasagi added a commit to Hanaasagi/struct-env that referenced this pull request Nov 29, 2023
mk12 added a commit to mk12/blog that referenced this pull request Dec 26, 2023
In particular, the removal of openIterableDir:
519ba9bb654a4d5caf7440160f018b7a3ae1e95a

and the removal of std.meta.trait:
ziglang/zig#18061
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking Implementing this issue could cause existing code to no longer compile or have different behavior. standard library This issue involves writing Zig code for the standard library.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants