ChanServ changed the topic of #zig to: zig programming language | https://ziglang.org | be excellent to each other | channel logs: https://irclog.whitequark.org/zig/
wootehfoot has quit [Read error: Connection reset by peer]
laaron has quit [Quit: ZNC 1.7.1 - https://znc.in]
laaron has joined #zig
laaron has quit [Quit: ZNC 1.7.1 - https://znc.in]
laaron has joined #zig
laaron has quit [Client Quit]
Ichorio has quit [Ping timeout: 264 seconds]
qazo_ has joined #zig
laaron has joined #zig
qazo has quit [Ping timeout: 258 seconds]
laaron has quit [Quit: ZNC 1.7.1 - https://znc.in]
laaron has joined #zig
laaron has quit [Client Quit]
laaron has joined #zig
laaron has quit [Client Quit]
laaron has joined #zig
earnestly has quit [Ping timeout: 258 seconds]
rjtobin has joined #zig
laaron has quit [Remote host closed the connection]
earnestly has joined #zig
laaron has joined #zig
shritesh has quit [Quit: shritesh]
kristoff_it has quit [Ping timeout: 244 seconds]
earnestly has quit [Ping timeout: 268 seconds]
laaron has quit [Remote host closed the connection]
laaron has joined #zig
ntgg has joined #zig
ntgg has quit [Ping timeout: 245 seconds]
rjtobin has quit [Remote host closed the connection]
darithorn has quit [Read error: Connection reset by peer]
ntgg has joined #zig
mrkishi has quit [Ping timeout: 260 seconds]
ntgg has quit [Ping timeout: 245 seconds]
crimson_penguin has quit [Ping timeout: 264 seconds]
crimson_penguin has joined #zig
porky12 has joined #zig
<bgiannan> Here's 2 attempt at OOP-like patterns: https://0x0.st/zWhq.zig
<bgiannan> first is with tagged union, and second with packed structs
<daurnimator> tgschultz: ^ thoughts?
<bgiannan> is there an easier way to do this?
earnestly has joined #zig
mmx870 has quit [Ping timeout: 244 seconds]
qazo_ has quit [Read error: Connection reset by peer]
qazo has joined #zig
<daurnimator> bgiannan: there's usingnamespace
<daurnimator> bgiannan: have your .init take a slice and mem.copy it into the unit name
ntgg has joined #zig
<daurnimator> Sahnvour: see also #2773
SimonN has quit [Ping timeout: 268 seconds]
SimonN has joined #zig
SimonNaa has joined #zig
<Sahnvour> daurnimator: thanks
SimonNaa is now known as SimonNa
SimonN has quit [Ping timeout: 245 seconds]
andersfr has joined #zig
andersfr has quit [Client Quit]
ntgg has quit [Ping timeout: 245 seconds]
Ichorio has joined #zig
laaron has quit [Quit: ZNC 1.7.1 - https://znc.in]
laaron has joined #zig
qazo has quit [Ping timeout: 245 seconds]
wootehfoot has joined #zig
<andrewrk> Sahnvour, the libc zig provides for windows is fully operational for: i386-windows-gnu, x86_64-windows-gnu, aarch64-windows-gnu, arm-windows-gnu
<daurnimator> andrewrk: you skipped doing a stream this last week?
<andrewrk> the build artifacts produced with this ABI are binary-compatible with the MSVC ABI
<andrewrk> that's right. need to finish up #3115 and catch up on bugs
wootehfoot has quit [Read error: Connection reset by peer]
<daurnimator> andrewrk: with 3115; can struct fields be bit aligned?
<daurnimator> andrewrk: and also, what is interaction between packed struct, bit fields and child struct alignment?
<andrewrk> daurnimator, not yet, but it's a prerequisite to doing that. I don't understand the second question
<daurnimator> andrewrk: e.g. I have a packed struct with a child field with alignment 16: `A = packed struct { x: align(16) u64 }`. Now I put it in another one: `B = packed struct { y: u4, a: A }`
<daurnimator> I guess that would be an error of "trying to put struct with alignment A inside of packed struct with alignment 1:4"?
<daurnimator> better wording: "trying to put struct A with alignment 16 inside of packed struct at alignment 1:4"
<andrewrk> it will be allowed to do that, and the packed struct would gain the alignment 16
<andrewrk> packed structs are going to become more powerful and useful
<daurnimator> andrewrk: but wouldn't the packed struct need to be placed at 4 bits *before* an alignment of 16 ?
<andrewrk> @sizeOf(B) would be 32
<andrewrk> there would be 15 bytes of padding after y
<daurnimator> its a packed struct; there shouldn't be any padding
<andrewrk> oh that's right. it means to ignore the alignment requirements. but @sizeOf(A) would be 16. so @sizeOf(B) would be 17
<daurnimator> andrewrk: sounds dangerous: it should error instead of ignoring IMO...
<andrewrk> actually, it can ignore the padding after the last field. so it would be 9 bytes. this is consistent with integers in packed structs
<andrewrk> there's no danger, the alignment as part of pointer types makes everything safe
<daurnimator> andrewrk: howso? e.g. imagine I define an impossible struct: when does it error? `C = packed struct { x: align(16) u8 }` `D = packed struct { c1: C, c2: C }`
wootehfoot has joined #zig
<andrewrk> daurnimator, non-explicit field alignment in the second packed struct is ignored. so you end up with c1 and c2 both 1 byte, each 1-byte aligned
<andrewrk> and if you take the pointer to c1, you get `*align(1) C` which the compiler knows is under-aligned
<daurnimator> andrewrk: what if I try and just instantiate a D on the stack? ignoring the alignment requirements of c2 seems dangerous...
<andrewrk> it works fine. try to come up with an example that is problematic and you will be thwarted by the alignment as part of the pointer property
<andrewrk> this is the same thing as integers in status quo packed structs
<Tetralux> Just so I'm clear, does that mean that `packed struct { x: align(16) i32; }` and then `.x` gives you `align(X) i32` instead of `align(16) i32` ?
<andrewrk> I've yet to hook this up in #3115 but explicitly specifying an alignment in a packed struct will be respected; ABI alignment of the type will be ignored
<Tetralux> Ah okay - I thought about this a bit when implementing the parsing/rendering and that does seem like what you want.
<Tetralux> If multiple fields are aligned in a non-packed struct, then padding is inserted?
<andrewrk> you will be able to match an extern struct with a packed struct by doing `x: X align(@alignOf(X))` for every field
laaron has quit [Remote host closed the connection]
* Tetralux nods
<Tetralux> What happens if the struct is non-packed?
<daurnimator> huh... `zig run --cache off --verbose-ir an_empty_main_function.zig` fails for me on master
<andrewrk> non-packed, non-extern structs have no defined in-memory layout. the fields can be in any order and there may be extra. however it is guaranteed that pointers to fields will be ABI aligned
<daurnimator> known issue with --verbose-ir? ^^
<Tetralux> Does that mean that pointers to fields in the struct will be aligned as per the field declaration?
<andrewrk> that's right
<andrewrk> daurnimator, sounds like an easy fix, probably trying to print something that can be null
<Tetralux> Okay, and in packed structs, the only difference is that default alignment is 1, so any field you mark aligned, will get a pointer that is aligned
<Tetralux> .. just as it does in non-packed?
<Tetralux> I feel like there should be a doc entry about this if there isn't already. xD
laaron has joined #zig
laaron has quit [Client Quit]
<daurnimator> andrewrk: seems to be the assert in render_const_val_ptr failing
qazo has joined #zig
<daurnimator> It's getting passed a ZigTypeIdFn instead of a ZigTypeIdPointer
<andrewrk> Tetralux, agreed. years ago this stuff seemed mysterious to me but now it's crystal clear. So, it's a good time to write docs on it
laaron has joined #zig
laaron has quit [Remote host closed the connection]
<Tetralux> andrewrk: Sounds good to me :)
<daurnimator> working around that assert I get another one in ir.cpp buf_write_value_bytes hitting the ContainerLayoutAuto branch
* daurnimator is too far down this yak shaving path now
<daurnimator> would be great if someone could look at getting --verbose-ir working again though
<andrewrk> I use it constantly, but only on small files, which have an overridden panic function
<andrewrk> otherwise it's too much output
<daurnimator> I tried overriding panic and had the same issues...
<daurnimator> andrewrk: that fails with same issue for me
<andrewrk> I'll check it in a bit. all 4 of my zig clones have wip stuff in them
<daurnimator> :P
<Tetralux> I'm rebuilding fresh rn, but I'll check once done just for giggles
<daurnimator> andrewrk: oh. it works with build-obj. build-exe and run fail for me.
<andrewrk> build-exe drags in a lot of the std lib
<andrewrk> --verbose-ir is intended for debugging minimal test cases
<daurnimator> yeah I was trying to debug/figure out #2850..... now I have that working with build-obj. But turns out I can't read LLVM IR :P
<andrewrk> LLVM IR? or zig ir?
<andrewrk> zig ir is admittedly arcane
<daurnimator> oh, zig ir
* daurnimator tries reading llvm ir instead
<andrewrk> at least with llvm ir you have http://llvm.org/docs/LangRef.html
<andrewrk> zig ir is defined by the functions ir_analyze_instruction_foo
<daurnimator> okay fun.... maybe this is an LLVM bug rather than a zig bug? I see a `%17 = zext i10 %16 to i64, !dbg !1420` in there.... my working theory for the bug was that that sort of zext was missing in there
<daurnimator> ==> the result of a zext on an i10 is ending up as 65535. which is above the max of 1023 you would expect
<andrewrk> is this an optimized build or no?
<daurnimator> optimized build of.... ?
<daurnimator> (the test case? zig? llvm?)
<andrewrk> do you observe the problematic runtime behavior without --release-fast?
<daurnimator> Yes. I have not used --release-fast at all
<Tetralux> Hmmm. When building Zig, the "unable to find lib directory" error; where does the lib directory come from?
<bgiannan> daurnimator, what does usingnamespace do? the only mention of it is in the grammar section
<daurnimator> bgiannan: it's undocumented as we don't really want people using it.... what is does is essentially add another struct to the current struct
<Tetralux> Behaviorally, it pulls symbols into the current namespace, from the given namespace.
<andrewrk> Tetralux, it's relative to the zig executable
darithorn has joined #zig
<Tetralux> Hmmm. It seems like the build step doesn't copy zig.exe to bin\zig
<andrewrk> the build instructions say to do `make install`
<Tetralux> On Windows? xD
<andrewrk> or on windows, `msbuild -p:Configuration=Release INSTALL.proj`
<Tetralux> Oh - the Wiki says INSTALL.vcxproj
<Tetralux> But yeah - followed that wiki page.
<Tetralux> Doesn't appear to produce lib or copy to bin.
<Sahnvour> yeah about that, if the purpose is only to build zig, I'd advise you generate a ninja project, not msbuild Tetralux
<Tetralux> I tried that before. Didn't seem to work.
<Tetralux> I would like to keep my options open as to what I can do, and I'm not sure what ninja makes it hard to do
<Tetralux> But I'd rather avoid msbuild if I can.
<Sahnvour> `ninja install` is all it takes once cmake generated the build files
<Tetralux> Let me try ninja again
<Tetralux> "Generator Ninja does not support platform specification x64"
* Tetralux shrugs irratatedly
<Sahnvour> iirc ninja always builds x64 on windows
<bgiannan> daurnimator, "we don't really want people using it": so not really safe for me if it's removed or transformed in th efuture?
<Sahnvour> Tetralux: so it's only the flag that is unsupported, otherwise it's fine
<Tetralux> Tried that already
<Tetralux> Removed all reference of x64 from the cmake invocation
<Tetralux> Still no
FireFox317 has joined #zig
<daurnimator> bgiannan: we tried to remove it but it was just too necessary for certain things. If it ever did get removed I think would be merged with whatever the solution to https://github.com/ziglang/zig/issues/1214 is
<FireFox317> Is a variable declared as a top level decleration suppose to be comptime known or not?
<Tetralux> I don't think so?
<Tetralux> It's a global.
<Tetralux> Unless I'm totally misunderstanding you somehow xD
<FireFox317> I.e. `var foo: SomeStruct = undefined` as a top level decleration
<FireFox317> Yes that is what I mean, it should not be comptime known right?
<Tetralux> No.
<Tetralux> Sahnvour: Also, I got further. I forgot to wipe the content of the build dir first xD
<Tetralux> But it still then emits loads of C++ errors.
<FireFox317> Okay, because i'm working on a bug, and if i change the declaration to `var foo: *SomeStruct` it thinks its not comptime, which is correct. But `var foo: SomeStruct` isn't comptime known according to zig master
<Tetralux> Maybe you have to explicitly mark that as comptime.
<daurnimator> bgiannan: see https://github.com/ziglang/zig/issues/2014 if you want some history
<Tetralux> Sahnvour: I think it's trying to use my mingw64 c++ compiler rather than clang or something maybe.
<Tetralux> But I'm not sure how I'd override that.
<andrewrk> FireFox317, the ConstExprVal sees it as ConstValSpecialStatic, but a pointer to it will have ConstPtrMutRuntimeKnown
<andrewrk> the pointer itself is comptime known, although the address itself is not known until link time, but the memory it points to is runtime known
<Tetralux> Sahnvour: Okay - I figured it out. -DCMAKE_CXX_COMPILER=full/path/to/clang/using/forward/slashes -DCMAKE_C_COMPILER=full/path/to/clang/using/forward/slashes
<Tetralux> I'm amused however that use of backslashes is fine with msbuild
<Tetralux> and make
FireFox317 has quit [Remote host closed the connection]
FireFox317 has joined #zig
<FireFox317> thanks andrewrk
<mikdusan> daurnimator: i think you're right - llvm zext on sub 8-bit sizes is suspect
<daurnimator> mikdusan: oh? where do you even look to find the implementation of that sort of thing?
<Tetralux> Sahnvour: Also debug build still fails for some reason. xD
<mikdusan> daurnimator: i suppose llvm upstream. I noticed that zext is operating on i10 as if it were i16 so whatever memory is there, in your reduction it's 0xffff, that's what it ops on. instead of 0x3ff
<daurnimator> mikdusan: I don't know my way around LLVM at all. greping around I found https://github.com/llvm/llvm-project/blob/1475fad1d0d45572471575cdda8fed6eeab5b0ec/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp#L625 but not sure if relevant
<daurnimator> mikdusan: otherwise I guess it falls to the target specific code? i.e. https://github.com/llvm/llvm-project/blob/0c476111317cb7aaa9a3e9f75e1c35f83122ee26/llvm/lib/Target/X86/X86InstructionSelector.cpp#L776 for most of us?
avoidr has joined #zig
<andrewrk> a small llvm ir test case that repros the problem would go a long way toward getting this fixed
<mikdusan> another hint: x86_64 ends up as `movzwl` Move Zero-Extended Word to Long, without regard to our i10 size
<andrewrk> ah thanks. I hadn't checked the issue yet
<andrewrk> i10 is represented by llvm as an i16
<mikdusan> well that explains it
<andrewrk> so at the zext instruction, the unused bits of the 2 bytes are assumed to be zeroes
<daurnimator> why are they assumed to be zeroes?
<mikdusan> assumed by who? llvm or zig?
<andrewrk> if you ask llvm what the "store size" of i10 is, the answer is 2
<mikdusan> i don't think llvm assumes it's zero. it just takes whatever value happens to be there and performs zext i16
<andrewrk> I agree
<andrewrk> but I believe the result is undefined if the unused bits are not zero
<mikdusan> does this mean zig will have to explicitly mask?
<andrewrk> this code does a pointer reinterpretation and then does not correctly set the bits of the reinterpreted memory
<andrewrk> that means the value of the i10 is undefined
<FireFox317> andrewrk: I found a fix for #3046, however maybe it is not the correct way to solve the issue. Do you want me to make a PR?
<andrewrk> FireFox317, sure, that will at least help, and then I can see if I can try to improve it
<andrewrk> thanks for looking into it
<andrewrk> setting all bits of an integer to 1 produces a well-defined value only when the integer is byte-aligned
<andrewrk> zig would be allowed to, for example, use the extra bit from a u15 to indicate that the integer is undefined
<daurnimator> interesting. if I change to a `packed struct { x: u10, y: u6 }` then the LLVM IR contains a truncation: `%9 = trunc i16 %8 to i10` `%10 = zext i10 %9 to i64`
<mikdusan> assuming re-interpration was corrected to only change i10 bits, then `= undefined` or random stack value of remaining 6 bits is still there for zext to use
casaca has quit [Ping timeout: 268 seconds]
casaca has joined #zig
<daurnimator> workaround? `packed struct { x: u10, y: u0 }` adds in a trunc....
<daurnimator> /bed
<andrewrk> good night daurnimator
<mikdusan> andrewrk: ok if I add some of your comments from IRC to the issue?
<andrewrk> mikdusan, yes
<andrewrk> I think I could probably try to make it a bit clearer though
<andrewrk> ultimately, the thing that is happening here is that u10 has a "bit pattern" that is not being respected by the pointer reinterpretation
qazo has quit [Ping timeout: 246 seconds]
curtisf has joined #zig
Akuli has joined #zig
<curtisf> what would be the best way to test that a simple allocator is correct? I wanted one to replace the fixed buffer allocator that can actually reclaim memory, but not confident I haven't made many mistakes. The allocator interface is a bit complicated, so hoping there's something I could reuse
<andrewrk> curtisf, there are some tests in std/heap.zig that work on the allocator interface itself
<andrewrk> it would be neat if someone made a zig project that was a comprehensive allocator test suite and benchmark suite. maybe there is an existing C codebase that could be adapted
xeqtr has quit [Ping timeout: 272 seconds]
<mikdusan> basic question: are non-power-2 integer type POINTERS actually useful? they seem to be incompatible with hardware and as soon as we use them it's a ub-fest
<mikdusan> (non 8-bit multiple)
<FireFox317> andrewrk: I added an extra check (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) that was missing in ir_analyze_struct_field_ptr. I saw the same pattern in for example ir_analyze_unwrap_err_code. I'm pretty sure that solves the issue, but it causes a segfault when building the compiler
<FireFox317> I'm gonna make a PR of it anyways, so that you can later have a look at it
<Sahnvour> Tetralux: I thought you used msvc, did you succeed to do what you wanted in the end ?
<Tetralux> Sahnvour: It did build in the end yeah. In order to make it work, I had to use clang since using MSVC means having to run vcvars.bat with the arch, which was x64 - which is what was causing Ninja to try to do x64 - which Cmake refused to allow.
<Tetralux> It worked, and runs fine so far though.
<Tetralux> I had to use clang-cl.
<Sahnvour> I don't understand your prblem with x64
<Tetralux> I don't either.
<Tetralux> Cmake just told me that Ninja didn't support that.
<Tetralux> When I removed the reference to x64, it worked - I just had to use abspaths to clang-cl.
<Tetralux> (.. and hence specify CMAKE_CXX_COMPILER and CMAKE_C_COMPILER.
<Tetralux> But it worked in the end.
<Tetralux> curtisf: That reminds me that I actually toyed with a RingAllocator a couple of weeks ago.
<Sahnvour> yes that's what I was saying: ninja only does x64, so cmake doesn't support the x64 flag when generating ninja, it is implied
<Tetralux> Sahnvour: Without pointing it clang explicitly, it could not compile the LLVM stuff because it was trying to use my mingw64 installation.
wootehfoot has quit [Read error: Connection reset by peer]
ntgg has joined #zig
<Sahnvour> makes sense
Akuli has quit [Quit: Leaving]
porky12 has quit [Quit: Leaving]
ntgg has quit [Ping timeout: 244 seconds]
<Tetralux> What's the story with logging in Zig?
curtisf has quit [Remote host closed the connection]
<fengb> Would a network socket write have the same interface as the current file write?
FireFox317 has quit [Ping timeout: 245 seconds]
ky0ko has joined #zig
<mikdusan> current interface doesn't indicate nbytes actually written
<mikdusan> *file interface
<fengb> I'll code to current file interface and fix it later >_>
mmx870 has joined #zig
dingenskirchen has quit [Quit: dingenskirchen]
mrkishi has joined #zig
ltriant has joined #zig
dingenskirchen has joined #zig
<andrewrk> mikdusan, it always writes all of them
<andrewrk> I do think that std.os.write should change to return how many bytes actually written
<Tetralux> I thought it wasn't a gaurentee?
<andrewrk> Tetralux, re: logging: https://github.com/ziglang/zig/issues/2586
<fengb> I’m fiddling with encoding / serialization and it seems like the async can be hidden behind fs.write
<andrewrk> yep. I'm in the middle of that same fiddling (except with fs.read) and I'm guessing you're going to run into the same issues that I have (which I'm working on solving)
<fengb> Ah okay. I had some raw async generators but ended up migrating towards fs magic
<fengb> So this seems like a natural abstraction point
<andrewrk> rest assured I don't consider the async/await proof of concept complete yet. I'm working up to a meaningful demo
<andrewrk> as a side effect, we're going to get safe recursion
<andrewrk> it's time
<fengb> Sure, I think semantically this makes a lot of sense. It’s also feels a bit odd that we get async for “free”
<andrewrk> can you elaborate?
<fengb> I mean, it’s great that it happens. It’s also feels foreign
<andrewrk> you mean that you can use `async` with any function?
<fengb> The fact that I’m codifying to fs interfaces synchronously means that having async network will magically get me async
<andrewrk> ah yes. I think it will work though! the only downside will be around function pointers. I'll push some code to a branch and show you
<fengb> Yeah. It’s great, but it’s also foreign compared to all the other envs I worked with
<fengb> Where async requires special logic
<andrewrk> have a look at the new InStream
<andrewrk> so the downside here is that function pointers (aka virtual dispatch aka interfaces) have a globally hard coded stack size for when it has to call the function pointer
<andrewrk> ...but it is safety checked, and if you ever hit the limit, you can just bump it globally
Ichorio has quit [Ping timeout: 264 seconds]
<andrewrk> and the thing that is actually quite elegant here, is that the stack size applies to both blocking and async. for async it's the function frame; for blocking it's yet to be implemented but function pointers will be annotated with stack size which works a lot like pointer align
<andrewrk> so most code can be agnostic; but the seams are leaky around function pointers
<fengb> Ah I see
<fengb> I’ve actually been using comptime duck typed read/write
<andrewrk> that has the advantage of avoiding the function pointer thing
<andrewrk> as well as issues with error sets
<Tetralux> You mean like `fn f(writer: var) { writer.write(buf); }` ?
<mikdusan> when std.io.is_async -> `try self.read(buf);` is that equiv to `try await async self.read(buf);` ?
<andrewrk> mikdusan, yes
<Tetralux> I still haven't really got my head around how to use async fns properly.
<fengb> Would it be helpful having a couple of []u8 based streams in std? I’ve been building some really dumb ones for testing purposes
<fengb> Fixed buffer and ArrayList
<Tetralux> I'm in two minds about that.
<Tetralux> The positive being able to make a stream from a buffer...
<Tetralux> Which is good.
<Tetralux> But if it's not efficient, I ain't interested.
<Tetralux> I've been thinking about that exact thing with regards to my CBOR encoder.
<fengb> My duck typed version is very efficient. Not sure if it’s behind a function pointer though
<Tetralux> What I kinda want is a Writer interface which works on anything that has a .write([]u8) and a .writeByte(u8) fn.
<Tetralux> But it has to avoid a fn ptr.
<Tetralux> It must be a static call; inlined if possible.
<Tetralux> #ZeroCostAbstraction.
<Tetralux> I originally just passed an ArrayList to it. xD
<Tetralux> But I want to be able to easily make streaming work.
<Tetralux> Like - I want to write an encoder that works on fixed buffers and streams man xD
<andrewrk> fengb, when I've been saying function pointer, I mean "runtime-known function pointer". So if you're using duck typing, you're probably not using that
<fengb> Yeah I'm not
<fengb> I'm curious if we can generalize duck typing into an interface construct
<andrewrk> I believe there is an open proposal for that
<fengb> Tetralux: here's my progression from top level async generator => async context with recursion => writer "interface"
<fengb> Async disappeared from the stack entirely and pushed directly onto whatever the writer does. It feels really good that this could just work™
<mikdusan> Tetralux: as I understand it the only way to #ZeroCostAbstraction is through comptime functions which then pushes the cost to code-size
<Tetralux> fengb: I'd have to see it to judge it reasonably.
<Tetralux> mikdusan: Both is possible.
<mikdusan> i'd like to see that ;)
<Tetralux> In 99% of programs, code size is less important than speed.
<Tetralux> 1MB is okay for a game, for example.
<mikdusan> right, it's still a trade-off nonetheless
<fengb> Codesize might actually be better for comptime style. A lot of the "generic" usecases end up having a usecase of 1 and comptime could compress that better than function pointers
<Tetralux> +1.
<presiden> +1
<fengb> It’d be super magical if our interface could optimize for either usecase seamlessly.
<andrewrk> I'm holding out for that
<Tetralux> How do you envision it being able to do that?
<andrewrk> I don't want to settle for anything less until it's proven that it's not possible
<Tetralux> Wait
<Tetralux> Just for clarity
<Tetralux> We want "Interfaces that can, with identical Zig code, optimize for speed or code size?"
<Tetralux> Is that what we're talking about here?
<andrewrk> for virtual dispatch or static dispatch
<mikdusan> i think we're talking about runtime vs comptime magic
<andrewrk> interfaces that express intent precisely; such that they work seamlessly at comptime or runtime, and --release-fast or --release-small could do the appropriate codegen
<mikdusan> maybe oversimplified; the way i see it is static dispatch multiplies each call site body codesize, and runtime dispatch multiplies each call site call-time
<Tetralux> Hmmm.
<mikdusan> hooking into --release-fast / --release-small is a splendid idea. and for many other things too i bet.
<companion_cube> I heard swift has an interesting solution to the generics bloat problem
<companion_cube> like a dictionary-passing technique that also carries sizeof() info
<Tetralux> It's worth noting that there is maybe some tricks you could do.
<Tetralux> Much like how CBOR does negative integers.
<presiden> witness table for swift, dict passing for haskell/ocaml
<Tetralux> Positive and negative integers are designed such that a negative number is -1, minus a positive number.
<Tetralux> This means that to get the positive value to encode, from the negative number,
<Tetralux> you can do
<Tetralux> ... basically you can use XOR.
<Tetralux> var sign = signof(value); sign ^= value;
<Tetralux> This removes the sign, and computes the appropriate value in either case.
<Tetralux> .. meaning you take the same codepath for both.
<Tetralux> The point being, there may be ways for Zig to also do that kind of thing with interface dispatch.
<Tetralux> Just something to bear in mind.
<companion_cube> also Zig has dependent types, the potential for bloat is big
<Tetralux> Dependant meaning what?
<companion_cube> types depending on values
<companion_cube> (comptime values, that is)
<Tetralux> Can you provide an example of what you actually mean?
<fengb> ArrayList
<Tetralux> If you mean the T in ArrayList(T), then you mean generics xD
<shachaf> I wouldn't call depending on comptime values "dependent types".
<shachaf> (And I don't think a language like Zig should have dependent types.)
<companion_cube> Tetralux: ArrayOfLen(T, 32) could be a thing
<companion_cube> shachaf: how is it not dependent types?
<companion_cube> if you can generate a type based on a comptime value
<companion_cube> (it's useful, you can do stuff like B-trees parametrized over their branching factor, or skiplists, or whatever)
<shachaf> Dependent types are usually types that depend on runtime values.
<shachaf> "compiletime" things are a lot more like type-level things.
<Tetralux> To me, things are generic if they depend on types or values.
<Tetralux> ... i.e: be it the '32' or the T.
<Tetralux> Both are generic parameters.
<Tetralux> But that's not the important part
<companion_cube> shachaf: wait, what
<companion_cube> dependent types are just types depending on values, at compile time (at run time it doesn't make much sense)
<Tetralux> 'Dependant type' is a type theory thing, isn't it... xD
<companion_cube> yes
<companion_cube> (in my book it's a good thing :p)
<Tetralux> God I hate type theory xD
<Tetralux> "Generic over values" seems less buzzwordy to me.
<companion_cube> why? a lot of modern improvements to languages come from there
<shachaf> With dependent types you can have e.g. index : Array n a -> Fin n -> a, where n is only known at runtime.
<Tetralux> Or rather, "over _a_ value."
<companion_cube> shachaf: then you need a forall
<Tetralux> Going back to the interface thing for a minute, the simple case isn't necessarily too hard; if a fn takes a Writer, the compiler would know they both could be passed to a write([]u8) function and might not even need to do any extra work for that.
<Tetralux> Like, if the call is not inlined, does the caller even need to know how write works?
<Tetralux> If not... just cast *Writer to *T and pass it?
<Tetralux> I have a feel I'm being stupid right now but you get my point xD
earnestly has quit [Ping timeout: 245 seconds]
<mikdusan> how can *both* be passed to a (single?) write function
<fengb> I think the goal is the compiler decides the passing style
<mikdusan> oh in the context of "magic" . gotcha
<fengb> Similar to how the compiler decides whether to pass args by value or reference
<Tetralux> I think I'm just being stupid and thinking of static dispatch when I'm trying to visualise a way to minimize code bloat for interfaces.
<Tetralux> It's been like 30C here for the past week and I've been sweating like a madman the entire time.
<Tetralux> It's draining, I'm sorry XD
<fengb> I like the concept but it also sounds really complicated
<shachaf> Eliminating arbitrary indirect jumps seems good for many reasons, including bounding stack space.
<Tetralux> fengb: Not necessarily complicated.
<Tetralux> It depends on a few things.
<Tetralux> But the short version is that, Zig member fns are not in the struct at all, right?
<Tetralux> Structs are just POD.
<fengb> Right now, I just used comptime duck typing because it’s easier to write, but it makes dynamic dispatch a little wonky
<Tetralux> Basically I'd like it to stay that way.
<companion_cube> is zig going to get closer and closer to rust? :p
<companion_cube> (except for the lifetime thing)
<Tetralux> OH GOD YES NEVER MENTION THE LIFETIME THING IN MY PRESENCE AGAIN
* Tetralux grins
<mikdusan> i admit it would be neat; say we have runtime interfaces all spelled out for uber uring I/O; compiler determines hello.exe only uses filesystem random file access and static'ifys the calls.
<fengb> I don’t think this is conceptually complicated
<fengb> ... so not like Rust :troll:
* Tetralux Eyyyyy
<mikdusan> :_:
<fengb> But I have no idea how this could be captured semantically
<companion_cube> how is rust conceptually complicated, on the generics side?
<Tetralux> <<<<><>><<<>>><<<<<<><<><>>
<companion_cube> that's syntax
<Tetralux> Iterator<Chain<Zip<Reverse<T>, InOrder<U>>>>
<fengb> Zig doesn’t even have real genetics. It just managed to use comptime to build it almost seamlessly
* Tetralux grins
<companion_cube> Tetralux: `impl Iterator` ;)
<Tetralux> companion_cube, Yes. Also that.
<companion_cube> comptime is a seriously complicated concept though
<Tetralux> I don't really see why.
<Tetralux> More complicated in power than in concept, perhaps.
<companion_cube> you need a full comptime interpreter, plus mandatory dead code elimination
<companion_cube> it also has very far reaching consequences
<Tetralux> Mandatory dead code elimination?
<companion_cube> for comptime if/for/while
<shachaf> At least you can use the same language for comptime and runtime, instead of using two different languages.
<mikdusan> yeah using a 2nd lang doesn't simplify things imo
<companion_cube> yeah, but it's know to be super tricky
<Tetralux> companion_cube: I still don't see why that needs dead code elim.
<shachaf> comptime if seems much simpler than dead code elimination.
<shachaf> (I mean, given that you have comptime evaluation.)
<companion_cube> well it's a form of dead code elimination, but yeah, it works
<companion_cube> also sounds to me like Zig doesn't yet have an answer to all the problems, in the absence of Drop
<shachaf> You don't need to detect whether code is dead or not -- it's not an optimization, it's just following instructions.
<companion_cube> "just" if you have an symbolic interpreter for untyped code
<companion_cube> not that easy