ChanServ changed the topic of #zig to: zig programming language | | be excellent to each other | channel logs:
<daurnimator> hey andrewrk: I think not having warning might be a mistaske
<daurnimator> *mistake
* andrewrk listens
<daurnimator> it really hamstrings future development: it becomes really hard to mark things as "deprecated"
<andrewrk> how about: deprecation is an error, and you can silence it explicitly if necessary
<andrewrk> s/deprecation/using deprecated things/
<daurnimator> now I can probably come up with a scheme for deprecating functions or even branches; but you also want to be able to deprecate or evolve e.g. builtins.
<daurnimator> or syntax (though I guess zig format handles that)
<daurnimator> though if the zig "header" equivalent is zig files.... then we're going to need to support old syntaxes for almost-ever.
<andrewrk> syntax, semantics, and builtins will be solved with a zig version number. packages will declare which version of zig they are built with
<andrewrk> when possible, newer versions of zig will support emulating older versions, so that packages can depend on each other even if they are built against different versions
<daurnimator> andrewrk: what do you think of adding a 'deprecated' attribute to functions?>
<andrewrk> I think it's definitely worth a formal proposal
<andrewrk> it makes sense to provide this functionality, as a way to improve package maintenance
<andrewrk> the use case is compelling
<andrewrk> but it will be an error to use the deprecated function, which you would then have to override - probably with a builtin that applies an override setting to the current scope
<daurnimator> I actually think it doesn't follow zig ethos that well; but it probably works well for system compatability: you can use the deprecated attribute in e.g. generated C headers too.
<andrewrk> that gives code readers another happy assumption: all the functions you see being called are not deprecated, unless annotated at the callsite
<andrewrk> (and if it's too much of a burden to annotate deprecated functions at the callsite, maybe you shouldn't upgrade to that library version yet)
<daurnimator> andrewrk: I like the idea of deprecated arguments too. e.g. fn foo(bar: ?u8[]) void { if (bar == null) { @deprecated("bar is now non-null") // handle old default here } // normalpath }
<daurnimator> ps, not having a terminate-able comment sucks for one-liners
<andrewrk> cramming lots of expressions into 1 line is not a supported use case of zig
<andrewrk> we will have to live with it being awkward in chat
<andrewrk> your example does a runtime check of the parameter
<andrewrk> but for a deprecation notice we would need to know at compile time whether a deprecated API is being used
<andrewrk> better strategy is to rename the function to foo2 and make the old one deprecated
<daurnimator> hrm. I don't love the idea of a rename; most users may e.g. already be using the non-null form
<andrewrk> I think it would be reasonable to just change it, and bump major versions
<andrewrk> since the only thing that could happen is a new compile error, which would be pretty easy to understand
<daurnimator> could you do: fn foo(bar: var) { if (@typeInfo(bar).pointer.nullable) { @deprecated().....
<andrewrk> you'd have to bump major versions anyway
<andrewrk> yes if we have @deprecated as a builtin, then you could do that, since the if expr is comptime known
<andrewrk> more complicated strategies make sense if the user's valid and working code would start being a runtime panic or bug
<andrewrk> otherwise, just change the signatures and rely on the compile errors
<andrewrk> zig is already designed carefully so that, usually, you could just change signatures, and you will get compile errors, or it will continue to work
<daurnimator> okay. so I think this suggests that a deprecated function attribute **and** a @deprecated() would be good.
<andrewrk> why and?
steveno has joined #zig
<andrewrk> you could put @deprecated in the first line of the function unconditionally
<andrewrk> and that makes it somewhat akin to a @compileError but that you can silence
<daurnimator> andrewrk: true. but I'm thinking for export to C; and also for annotating extern functions.
<andrewrk> good points
<daurnimator> andrewrk: so other warning-y things: @warn("this code path is untested, it *should* work, but we'd like to hear from you about your use-case")
<daurnimator> fn bar() { if (someglobal) { @warn("looks like you haven't called foo() first; this is usually (but not always) a mistake") } }
<andrewrk> that doesn't work, reading the value of a global variable is runtime-known
<daurnimator> ah, true.
<andrewrk> I also think the untested code path thing belongs in the documentation, not as a way to hassle the coder by making them override a warning
<andrewrk> deprecation is essentially a compile error, with a guaranteed to be available temporary workaround
<daurnimator> if it's a compile error, how do you get around it?
<daurnimator> zig build
<andrewrk> in code, in the scope where you use it
<andrewrk> so you have to do it N times for N call sites
<andrewrk> really, the best solution is to not upgrade package versions until you are ready to solve the deprecations
<daurnimator> I don't think that works if you're using external libraries.
<daurnimator> the whole point of a deprecation is that you can do it in a minor or patch version as an early warning of the next major version.
<daurnimator> it shouldn't "break by default"
steveno has quit [Quit: Leaving]
<andrewrk> deprecations in zig will bump major versions
<daurnimator> but also, I envisage a world where misc libraries ship with .zig "headers" in addition to their C .h ones. the system will want to deprecate things outside of a zig application development cycle
<andrewrk> that's a good point
<andrewrk> it could be something as simple as a global build flag - whether deprecation errors are enabled or not
<andrewrk> with "on" being the default
<daurnimator> Yes I considered that; but decided that you probably want fine grained per-deprecation control
<daurnimator> otherwise people will just enable it all the time and not see the *new* deprecations
<daurnimator> also "on" being the default seems like a -Werror like situation: should be on by default for development, but off by default for releases.
<andrewrk> ah that's an interesting idea
<daurnimator> (otherwise for the end user compiling from source, they get a screen full of deprecation warnings they can't/won't do anything about)
<daurnimator> andrewrk: any further comments here? Otherwise I will segue to another topic
<andrewrk> I agree, that situation is to be avoided
<andrewrk> I think that will be avoided by strict version locking
<andrewrk> if it builds for the developer, it should build for the user, even on later versions of zig
<daurnimator> but what about as system library interfaces change?
<andrewrk> are you talking about an ABI change? that's fundamentally broken
<daurnimator> a deprecation notice is the precursor to an ABI change.
<andrewrk> the developer will either fix the deprecations, or ship a version against the old system library interface package version
<daurnimator> okay; I'll think about that for a bit
<andrewrk> in zig projects, the goal is 0 system dependencies
<daurnimator> so related questions I have: how do I ship a library I write in zig?
<daurnimator> e.g. I want to write a library "" that is a normal system package; it should be usable from zig, C, fortran, etc. applications.
<andrewrk> that's to be determined with the package manager project. for now it's nothing more than a directory with .zig files
<andrewrk> right, ok that's a good use case
<andrewrk> you'll have your zig package, and then probably a file which has the exported API that suse the zig package
<daurnimator> "a file": please expand here
<daurnimator> a zig file (how would I create it?)? a C header (then we lose information)? something else?
<andrewrk> exports.zig which has export fn daurnimator_init, export fn daurnimatior_foo, etc
<andrewrk> the build system knows how to create shared libraries, so you'll communicate to the build system about libdaurnimator
<andrewrk> for it to be a normal system package, is a question for the system package manager. for example in debian the package build script would invoke zig build
<daurnimator> andrewrk: exports.zig is something autogenerated?
<andrewrk> no that's where you put your export functions, for example
<andrewrk> point being they're in a separate file because you don't want to export them in your zig package when you're not making a library
<daurnimator> and exports.zig is the only thing you "ship" into /usr/include?
<andrewrk> exports.zig is a source file. the zig compiler auto-generates .h files
<andrewrk> the auto generated source file would go into /usr/include
<daurnimator> isn't the conversion to .h lossy?
<andrewrk> sorry, auto generated .h file, not auto generated source file
<andrewrk> yes, it is. to get lossless use, use zig, and use the zig package, and ignore exports.zig since that's for creating the shared library
<daurnimator> but then I'd have to distribute the source; and the sources to the libraries I use.....
<daurnimator> also, any project is going to have "internal" structs that should be made opaque for export.
<andrewrk> that's why zig has @OpaqueType()
<andrewrk> zig has no stable ABI. if you want a stable ABI you have to use the C ABI
<andrewrk> so you either distribute a library as source, or you distribute it as a normal library, with a .h file and .so/.dll .a/.lib
<daurnimator> that seems..... bad
<andrewrk> can you elaborate? what use case is problematic and why?
<daurnimator> It's a bit of a jumble of thoughts:
<daurnimator> 1. closed source zig libraries should still be able to be exposed "first class" to zig applications/other zig libraries
<andrewrk> when I say zig has no stable ABI, I mean that zig only has the C ABI. it's not like you can accidentally have an ABI mismatch.
<andrewrk> not possible. consider that this is fundamentally impossible with generic functions
<andrewrk> and comptime code execution
<daurnimator> 2. I don't want to have to download the *source* of dependencies of a package I'm trying to install, and the source of the dependencies of the dependencies: the .so and some header should be enough
<andrewrk> why not?
<daurnimator> It makes compilation very.... un-self-contained.
<andrewrk> quite the opposite
<andrewrk> the fact that we build compiler-rt and parts of libc from source, for example, is why zig has good cross compilation support
<daurnimator> My build deps become more than just *my* build deps, but the build deps of my build deps of their build deps.... etc.
<andrewrk> having the source of all your dependencies is the ultimate way to be self-contained
<daurnimator> It means that e.g. my release tarballs need to include the source of all my dependencies too
<daurnimator> 3. it (probably) means that compile times go up and up as you use more dependencies: if there is a zig library 'A' that takes a long time to compile, I only want to pay it once when I compile, not when I use it again from libB or appC.
<andrewrk> you could choose to bundle your dependencies, yes, to enable offline builds, but since you already depend on zig, you could distribute only your project's source and rely on zig package manager to fetch the dependencies
<andrewrk> and note this only applies to the use case of shipping a C library as zig source
<daurnimator> You say "shipping a C library"... I'm really thinking of "shipping a zig library as not-source"
<daurnimator> So idea: could we have a zig 'stripper': that looks at a .zig file and removes all non-exported functions/types? (replacing unexported types with opaque types)
<andrewrk> as for compile times - there's plenty that zig can do to make this fast, including things such as caching and trusted pre-built binaries. but you always want the option to build from source
<andrewrk> because zig has no ABI, debug builds in zig are allowed to do all manner of tricks to enable incremental builds to be fast, as well as support pre-built artifacts
<andrewrk> you can ship binaries as non source but you cannot ship a zig package as non-source. it's not a coherent concept
<daurnimator> that doesn't match well with how distro builds and maitenence is done today.
<andrewrk> I don't understand the goal of your stripper tool. what would that accomplish?
<andrewrk> what problems do you foresee with distro builds and maintenance?
<daurnimator> andrewrk: e.g. the 'stripped' zig file would be installed to /usr/include/daurnimator.zig on the target system. it would allow zig applications to use
<daurnimator> this "stripped" zig file may contain comptime functions (similar to how C headers may include macros or inline functions). but it doesn't expose anything (including types) unless they were exported: everything else is replaced with opaque types.
<andrewrk> ah, I see. essentially using a .zig file instead of an .h file, but still with a pre-compiled library
<andrewrk> ok, that's a fine use case, we can have zig generate one of these .zig files alongside or as an alternative to a .h file
<andrewrk> better yet though - we would figure out how to add zig-specific annotations to .h files
<andrewrk> so that .h files could be lossless
<andrewrk> this would help when trying to translate c code as well; one could annotate the C code before translating
<daurnimator> andrewrk: that would be good too; but I don't think it would ever be "lossless"
<andrewrk> it's also less common of a use case than source distribution of packages. open source packages would never use this method
<daurnimator> I think most distros would prefer it
<andrewrk> distros can do whatever they want when they package up software, but zig programmers will prefer dependencies that do not rely on what is installed on the system
<daurnimator> I don't know about that
<daurnimator> I would like to say "use system library X" and not care if it's written in C, zig, or anything else
<andrewrk> you can do that now, and you will always be able to do that, but that adds a dependency on system library X. dependencies have costs, plus zig will not be able to optimize across system library boundaries or run system library functions at comptime.
<andrewrk> you've also opened up your project for users to file issues that stem from misconfigured or missing system library X
<daurnimator> andrewrk: in my "stripped zig" idea, you could have comptime functions in there (as long as they're exported)
<andrewrk> everything is worse when doing things this way. you lose the ability for global release mode such as Small to modify the binary; you lose call graph analysis; you lose generic functions, comptime functions
<andrewrk> open source library distributions are strongly encouraged
<andrewrk> or rather, not necessarily open source, but distribution *as source*. of course a company can have private servers or private code, etc
<daurnimator> andrewrk: people/distros are used to having a system default set of compile flags (usually -O2)
<andrewrk> you also lose coroutines and the ability to have a global event loop
<daurnimator> why do you lose call graph analysis?
<daurnimator> and why do you lose generic functions? (if they're exported; they'll be in the stripped output)
<andrewrk> you can't export generic functions. you're introducing a new concept to the language. the C ABI does not support generic functions
<daurnimator> andrewrk: you can return them from a module....
<daurnimator> perhaps s/extern/pub/
<daurnimator> uh s/export/pub/
_whitelogger has joined #zig
_whitelogger has joined #zig
errpr has quit [Ping timeout: 250 seconds]
fsateler has quit [Read error: Connection reset by peer]
fsateler has joined #zig
forgot-password has joined #zig
<forgot-password> Hi guys, is it possible to mutate struct fields?
Hejsil has joined #zig
<Hejsil> forgot-password, you should be able to do: instance.field = some_value;
<Hejsil> So yes
<forgot-password> Oh wait, maybe it didn't work because function parameters are constant. Could that be it?
<forgot-password> I guess so, it works outside of my function.
<forgot-password> Can I somehow declare my parameter as mutable?
<forgot-password> Alright, I got it. I just made it a pointer to my struct. Thank you :)
<Hejsil> Yes, if you want to have "side effects" then you need a mutable pointer :)
<Hejsil> Or a global variable
noonien has joined #zig
_whitelogger has joined #zig
steveno has joined #zig
_whitelogger has joined #zig
steveno has quit [Remote host closed the connection]
steveno has joined #zig
MajorLag has joined #zig
steveno has quit [Ping timeout: 260 seconds]
steveno has joined #zig
Hejsil has quit [Ping timeout: 256 seconds]
forgot-password has quit [Quit: Lost terminal]
Marumoto has joined #zig
steveno_ has joined #zig
steveno has quit [Ping timeout: 250 seconds]
Ichorio has joined #zig
Zaab1t has joined #zig
errpr has joined #zig
Marumoto has quit [Quit: Page closed]
errpr has quit [Ping timeout: 250 seconds]
steveno_ has quit [Ping timeout: 240 seconds]
Zaab1t has quit [Quit: bye bye friends]
caphetrosh has joined #zig
fsateler has quit [Read error: Connection reset by peer]
fsateler has joined #zig
Ichorio has quit [Ping timeout: 268 seconds]
<knebulae> printf