ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
32.18k stars 2.35k forks source link

Can't coerce sentinel-terminated pointer to slice #4826

Open donaldcallen opened 4 years ago

donaldcallen commented 4 years ago

zig build-exe --main-pkg-path .. --single-threaded -I/usr/include -L/usr/local/lib64 -L/usr/lib64 -lsqlite3 -lc pkg-config --libs gtk+-3.0 composite_register.zig Semantic Analysis [783/1023] /home/dca/Software/newcash_zig/common/common.zig:308:47: error: expected pointer, found '[]const u8' var account_names = mem.separate(@ptrCast([]const u8, account_path), ":"); ^ I find "expected pointer, found '[]const u8'" puzzling, since the documentation says "[]T - pointer to runtime-known number of items. " in the Pointers section. Either I'm missing something or this is a bug.

LemonBoy commented 4 years ago

Either I'm missing something or this is a bug.

@ptrCast is used to cast between pointer types and slices are not pointers, they're just a pointer to some memory plus a length field that may change at runtime. Use std.mem.spanZ to convert your null-terminated char arrays into a slice with proper length.

donaldcallen commented 4 years ago

I think the problem, at least for me, is that the Pointers section of the documentation is not clear. It does say at the outset that there are two kinds of pointers and then describes them. No issue there. It then goes on to say "These types are closely related to Arrays and Slices:", which is where the trouble starts for me. The ensuing description describes the array and slices syntaxes as "pointer to ...". So it is very unclear whether that notation is considered a pointer or not, especially since the word "pointer" is used in their descriptions.

Even in your comment above, you say slices are "not pointers" and then go on to describe them as "just a pointer ....". Either they are pointers or they aren't. If they aren't, the word pointer should not be used, especially in the official documentation.

But thanks for the tip on how to fix my code.

LemonBoy commented 4 years ago

Either they are pointers or they aren't. If they aren't, the word pointer should not be used, especially in the official documentation.

Slices are just a pointer + a number indicating the length of the slice.

These types are closely related to Arrays and Slices

That's why they are related. Nothing more, nothing less.

donaldcallen commented 4 years ago

You are continuing to overload the word "pointer", which is the primary issue of this discussion. I'm not going to continue to try to make you see that. I've stated my case that the documentation is confusing on this issue and should be fixed and will leave it at that.

JesseRMeyer commented 4 years ago

I thought I saw some changes to make the @ptrCast unnecessary by automatically inferring the array type was being made recently?

It may be easier to think of slices as fat pointers -- a struct that contains a data pointer and a length field:

slice = struct {
    data: [*]type,
    length: u64,
};
Tetralux commented 4 years ago

Personally, I've always disagreed with the notion that slices are "pointers". They are not. They are simply a view into a region of memory. The fact that they "point" to a region of memory is presumably why they are described as a type of pointer - but they are not. They are a struct--which yes, contains a pointer--but its purpose is simply so that you can pass around a region of memory.

donaldcallen commented 4 years ago

@Tetralux Yes, I understand all that. Again, the issue is not my accepting and understanding that slices are not treated as pointers by zig, but rather my contention that the documentation is confusing on this issue and should be fixed. I've posted this because I'm trying to help the project, in a small way. Confusing newcomers with bad documentation on a key issue is not a good way to encourage acceptance of the language. I am a very experienced writer of software and manager of software projects (and the documentation thereof). I say this not to blow my own horn but to emphasize that if the documentation confused me, what about the young 'uns?

By the way, I think you explained it quite well in your post. Something along the lines of what you wrote could be the basis for a fix to the documentation. I'd also suggest moving the discussion of arrays and slices out of the "Pointers" section. Their inclusion there sets the stage for the confusion. If they aren't pointers, why are they being discussed in a section entitled "Pointers"?

Tetralux commented 4 years ago

Yes, I understand all that. Again, the issue is not my accepting and understanding that slices are not treated as pointers by zig, but rather my contention that the documentation is confusing on this issue and should be fixed

No, no. I completely agree. If it sounded otherwise, apologies - not my intention.

I'd also suggest moving the discussion of arrays and slices out of the "Pointers" section. Their inclusion there sets the stage for the confusion. If they aren't pointers, why are they being discussed in a section entitled "Pointers"?

I'm inclined to agree with this too.

matu3ba commented 3 years ago

I think the problem, at least for me, is that the Pointers section of the documentation is not clear. It does say at the outset that there are two kinds of pointers and then describes them. No issue there. It then goes on to say "These types are closely related to Arrays and Slices:", which is where the trouble starts for me. The ensuing description describes the array and slices syntaxes as "pointer to ...". So it is very unclear whether that notation is considered a pointer or not, especially since the word "pointer" is used in their descriptions.

Even in your comment above, you say slices are "not pointers" and then go on to describe them as "just a pointer ....". Either they are pointers or they aren't. If they aren't, the word pointer should not be used, especially in the official documentation.

But thanks for the tip on how to fix my code.

Can you suggest an explicit formulation, which would be less confusing and remains dense like the current comparison of pointers and pointer-based structures (arrays and slices)?

Your current critique formulation is too vague on what restructuring you would suggest.

donaldcallen commented 3 years ago

I'm going to copy the current documentation here, for my convenience and yours:

Zig has two kinds of pointers: single-item and many-item.

These types are closely related to Arrays https://ziglang.org/documentation/master/#Arrays and Slices https://ziglang.org/documentation/master/#Slices:

In the first section, we are told that Zig has two kinds of pointers -- single- and multi-item.

Then in the second section, the first bullet says

"*[N]T - pointer to N items, same as single-item pointer to an array."

The second half of the above ("same as ...") makes sense w.r.t. the definition of a single-item pointer. But "pointer to N items"? What is this? A third type of pointer, to multiple items where the number is known at compile time? That's what this seems to say, but then it contradicts the first section, which says there are two types of pointers, not three. If you just took out "pointer to N items", I would have no trouble with this, although I'm not sure why "These types are close related ...". This is just an example of a single-item pointer to a particular type T where T=[N]T2, where I've added the '2' to distinguish between the type being pointed to (the array) and the type of the array items.

But now we have the problem that [N]T2, which we are told is the same as a single-item pointer, supports three operations. But T supports only one. If this really is the same as a single-item pointer to an array, why are three operations supported? Is this a special case in the language? None of this is explained. Totally confusing. This is not only a documentation issue, it brings up questions about the language design that need to be addressed/explained.

This is just an example of my frustration and confusion with both the language and the documentation. You've asked me to propose something more clear. I can't do that, because the documentation is so bad, so confusing, I don't know what is actually right. If I don't know what's right, how can I document it? Only someone who knows what's really in the language and can write clear documentation can fix this.

That's the best I can do for you.

/Don Allen

On Thu, 20 May 2021 at 15:10, matu3ba @.***> wrote:

I think the problem, at least for me, is that the Pointers section of the documentation is not clear. It does say at the outset that there are two kinds of pointers and then describes them. No issue there. It then goes on to say "These types are closely related to Arrays and Slices:", which is where the trouble starts for me. The ensuing description describes the array and slices syntaxes as "pointer to ...". So it is very unclear whether that notation is considered a pointer or not, especially since the word "pointer" is used in their descriptions.

Even in your comment above, you say slices are "not pointers" and then go on to describe them as "just a pointer ....". Either they are pointers or they aren't. If they aren't, the word pointer should not be used, especially in the official documentation.

But thanks for the tip on how to fix my code.

Can you suggest an explicit formulation, which would be less confusing and remains dense like the current comparison?

Your current critique formulation is too vague on what restructuring you would suggest.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ziglang/zig/issues/4826#issuecomment-845403933, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABGOGJ3DEOJKIHQBN7LDPA3TOVNBHANCNFSM4LUWCMAQ .

tariqkb commented 2 years ago

Personally, I've always disagreed with the notion that slices are "pointers". They are not. They are simply a view into a region of memory. The fact that they "point" to a region of memory is presumably why they are described as a type of pointer - but they are not. They are a struct--which yes, contains a pointer--but its purpose is simply so that you can pass around a region of memory.

I just want to add that this explanation helped me very, very much.

I've never done low level programming, but I have been learning through little projects in zig and it's been an absolute delight. I know I may not be the typical use case, but a table laying out what all the different syntaxes around pointers/slices/arrays mean would be hugely valuable. Understanding that slices are simply windows into memory made so much just click for me just now.

Again, not the typical use case, but this comment is the reason I finally fixed something that's been blocking me for a few days. Thanks again :)

matu3ba commented 2 years ago

table laying out what all the different syntaxes around pointers/slices/arrays mean would be hugely valuable

taken from ziglings exercise 054

syntax description
u8 one u8
*u8 pointer to one u8
[2]u8 two u8s
[*]u8 pointer to unknown number of u8s
[*]const u8 pointer to unknown number of immutable u8s
*[2]u8 pointer to an array of 2 u8s
*const [2]u8 pointer to an immutable array of 2 u8s
[]u8 slice of u8s
[]const u8 slice of immutable u8s

Do you believe sentinels should be added to the table as well? Taken from ziglings exercise 077

//     const a: [5]u8 = "array".*;
//     const b: *const [16]u8 = "pointer to array";
//     const c: []const u8 = "slice";
//     const d: [:0]const u8 = "slice with sentinel";
//     const e: [*:0]const u8 = "many-item pointer with sentinel";
//     const f: [*]const u8 = "many-item pointer";

What more is missing?

tariqkb commented 2 years ago

That's excellent, thank you. I haven't seen ziglings before, that's a very helpful resource

barathrm commented 7 months ago

Excuse me if things have developed which make some of the earlier posts on this issue invalid, but here's another factor which may confuse newcomers as to whether slices are pointers or not; you can actually use ptrCast with slices.

test "ptrCast slices" {
    const a_slice: []const u8 = &[_]u8{ 255, 0 };
    const another_slice: []const i8 = @ptrCast(a_slice);
    std.debug.print("\n{any}\n", .{another_slice});
}

Will currently (0.12.0-dev.1591+3fc6a2f11) print

{ -1, 0 }

There are also references in the zig source around ptrCast to enable ptrCast to cast between different lengths/types of slices. If we try to use ptrCast to cast from a slice of u8 to u16 for instance, we get:

src/main.zig:527:40: error: TODO: implement @ptrCast between slices changing the length
    const another_slice: []const u16 = @ptrCast(a_slice);
                                       ^~~~~~~~~~~~~~~~~

Does anyone know whether there's an issue ticket for this todo? I haven't been able to find any info on it.