Skip to content

Hacking-friendly "--sloppy" mode for Zig. #3320

@vi

Description

@vi

As far as I understand, Zig places great emphasis on code maintainability.

Unfortunately, restrictions required for it are at conflict with ease of development, debugging and prototyping.

I suggest to have a special Zig mode that trades code maintainability for short-term ease, ergonimics and speed of hacking. Command-line option may be --sloppy or --devmode or --lax.

Proposed rules for such mode:

  • When Zig would have a proper central package repository, the code is syntax-checked without --sloppy as a minimal acceptance test.
  • In Zig documentation, books and tutorials, users should be recommended to avoid publishing (or even checking in) --sloppy mode code.
  • Normal and sloppy mode choice should not be tangled with LLVM optimisation level, testing, assertion enabledness and other aspects that are typically different between debug in release.
  • Additional built-in and library functions may be available. Example: Proposal: port dbg!() from Rust #3296
  • Errors about unreachable code (and similar), as well as other non-critical errors are downgraded to warnings. Such warnings may be hidden. Similar for ignoring errors, missing switch cases and so on.
  • A warning may be emitted just for mere enabling --sloppy mode, as an eye sore reminding that it is not supposed to be permanently enabled.
  • Mere turning on --sloppy without modifying source code should not affect program behaviour.
  • Comptime functions may check for sloppy mode and @compileError if it is not enabled. The reverse should not be idiomatic.
  • Sloppy-only functions and language features are not considered part of Zig. They may be removed / changed even after Zig goes 1.0.0.
  • Stable, official versions of Zig compiler may omit support of --sloppy mode. Master builds may be required.

Activity

changed the title [-]Hacking-friengly "sloppy" mode for Zig.[/-] [+]Hacking-friendly "--sloppy" mode for Zig.[/+] on Sep 27, 2019
added this to the 0.6.0 milestone on Sep 27, 2019
added
proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.
on Sep 27, 2019
Srekel

Srekel commented on Nov 11, 2019

@Srekel

A suggestion for option name: --exploratory

Sorry for bikeshedding, but the topic came up on Discord a while back and someone said that "Zig is currently not great for exploratory code", or something to that effect, so that's where it comes from. :)

Sometimes, you just don't know exactly what you're building, or how you want to do it, so you're "exploring" how to write the code. (Especially true for people new to Zig.) Having to handle for example allocation errors when you "know" they won't happen slows you down more than it helps in this particular stage.

andrewrk

andrewrk commented on Nov 11, 2019

@andrewrk
Member

Related: #68

pixelherodev

pixelherodev commented on Nov 12, 2019

@pixelherodev
Contributor

The main issue with this idea (in my mind at least) is that it'll almost certainly result in people forgetting to turn the feature off, and then having to clean up a giant mess of code when they go to e.g. submit to a Zig package repository.

I think this idea is definitely workable, but it might need a tad more thought.

Another more minor issue: I don't think downgrading things like unreachable code to warnings is the best idea - that I think should show up as an even lower priority, as otherwise too many warnings could stack up quickly, making it hard to find what you're actually looking for. On the other hand, having it show up as a warning means there's a greater incentive to fix it, to clean up the warnings list even in --sloppy mode.

This definitely needs a lot more thought, though I do think it has merit.

vi

vi commented on Nov 12, 2019

@vi
Author

I don't think downgrading things like unreachable code to warnings is the best idea - that I think should show up as an even lower priority, as otherwise too many warnings could stack up quickly, making it hard to find what you're actually looking for.

Obviously, in the sloppy mode warning classes should also be ignorable.

For non-sloppy-mode usage, warnings should be ignorable on case-by-case basis, when unreachable code is by design due usage of to generic (comptime) tricks.

vi

vi commented on Nov 12, 2019

@vi
Author

people forgetting to turn the feature off, and then having to clean up a giant mess of code when they go to e.g. submit to a Zig package repository.

That's inevitable. It is also inevitable that sloppy-only libs that only live on Github, not on the official repository will apear.

But I assume there are many projects that don't come to the phase where it is reasonable to publish them (i.e. experiments). Pre-publishing cleanup (during which README, documentation, tests, etc. may be written) is simply not needed for them. Requiring clean code for everything (including one-off throw-away code) may be suboptimal.

Srekel

Srekel commented on Nov 13, 2019

@Srekel

Jonathan Blow just tweeted a thread (how timely! :) ) related to this: https://twitter.com/Jonathan_Blow/status/1194289482469502976

More of my perspective: I tend to always work in "full" warnings/warnings as error-mode in C/C++, so I appreciate releasing things where the code doesn't have hidden bugs or whatever.

But I agree with Blow here, and it probably needs to be more granular than on a project/build-wide setting? Like let's say you're working on a game and you're working on a subsystem that you want to fiddle with a bit before deciding on the final implementation, it makes sense to be able to mark that as sloppy, in some sense. I'm not sure if that can be easily solved in practice though... :)

And like @vi said, sometimes you work on something that you never have time to finish as a "proper" project, but that may still be valuable to people. Here's one of mine, https://github.com/Srekel/the-worldinator, it's not done yet and not sure if it ever will be, but I imagine someone might learn something from it.

vi

vi commented on Nov 13, 2019

@vi
Author

More of my perspective: I tend to always work in "full" warnings/warnings as error-mode in C/C++, so I appreciate releasing things where the code doesn't have hidden bugs or whatever.

hidden bugs or whatever

Some warnings are not about hidden bugs, but about maintainability. Notably unused code warnings (including unused imports and unused mutability). Those warnings are most often triggered by something being unfinished (although sometimes they point to a bug as well, but rarer).

For example, when I start doing things in Rust, I typically add #[allow(unused)] as soon as I see first of such warnings. Eventually this annotation goes away, as module stabilizes. It may reappear when heavy refactoring is undergoing. Something similar can happen in Zig projects. Start in exploratory mode, then go to normal mode. When reogranisation/refactoring happenning, switch the project back to exploratory mode for a while. For this it may be worth supporting specifying --sloppy both on command line (quick debugging sessions spanning minutes/hours) and inside source code (project reorg spanning days/a week).

"proper" project, but that may still be valuable to people

Nobody forbids publishing unuploadable-to-official-repository code to a github.

ghost

ghost commented on Nov 13, 2019

@ghost

Also related: #335 (proposal to add more errors for unused/unreachable things - these should be reduced to warnings in sloppy mode)

marler8997

marler8997 commented on Nov 14, 2019

@marler8997
Contributor

Instead of a command-line option, I would suggest some type of configuration inside the source code. If code is written in this sloppy mode, then it's not really a command-line "option" that you can enable or disable, it's a feature of the code itself. The code is either written in "sloppy" mode or it's not, so the code should declare what mode it's written in.

Allowing each source file to declare this also allows you to compile multiple modules with sloppy mode enabled/disabled on a per-module basis without having to invoke zig multiple times to enable/disable it for each one.

marler8997

marler8997 commented on Nov 14, 2019

@marler8997
Contributor

After reading more about this it actually may make more sense to make it a command-line option. I thought this was a permanent type of mode for zig source code, but it looks like it's just a temporary switch to aid in faster refactoring/development.

vi

vi commented on Nov 14, 2019

@vi
Author

@marler8997 , I think it should primairly command-line switch, but also triggerable from build.zig (making it permanent-ish for a project).

Production-oriented version of Zig compiler may reject both.

pixelherodev

pixelherodev commented on Nov 17, 2019

@pixelherodev
Contributor

Production-oriented version of Zig compiler may reject both.

I think that's a good idea.

40 remaining items

vi

vi commented on Jul 26, 2021

@vi
Author

--allow-unused-variables

There may be similar rule about unused mutability (var where const would also do). So it may make sense to have just --allow-unused (either instead or in addition to fine-grained warning controls).

dancojocaru2000

dancojocaru2000 commented on Oct 26, 2022

@dancojocaru2000

@andrewrk

A carpenter might have fun building something out of wood using a hammer and nails, but they don't use a "fun hammer". They just want an effective hammer,

Sure thing. But Go and Zig seem to be the hammer that makes your hand hurt while using it, which you only ever use when the other hammers you have don't do the job well.

Due to opinionated stuff like this (which are bad opinions, in my opinion), I only use Go when a library is only available in that language, and I only use Zig for its C/C++ compiler. Great job on that part of Zig, by the way! I only wish Zig itself would be better to use so I wouldn't have as much of an use for C/C++.

Since the lack of a "sloppy" mode actively prevents me from compiling and working, and breaks me out of my workflow to write bugs, Zig is actively trying to not be an effective hammer. If a hammer constantly gives me pain and forces me to readjust my grip, it's gonna be less effective than the hammer that just lets me use it to work.

and the fun part is the part where you build something.

These "features" make building something hard, frustrating, and seem to be specifically designed to make it not fun. It makes it so that when something finally gets built, it feels like it got built despite the language, not thanks to it.

vi

vi commented on Oct 26, 2022

@vi
Author

Is explicit, documented refusal to implement dev/permissive mode better than endless postponing of it?
It may promote creation of some separate, independent project to make Zig development easier. Such as:

  • Special language server that tracks edit history and keeps idiomatic Zig code on disk and dev-friendly Zig code view in IDE.
  • "Giz" programming language that is suspiciously similar to Zig (and can use Zig's modules as is). Allows existence of sloppy code without tarnishing the Zig brand.
  • Zig code preprocessor as a separate dev-only built step.

Zig development proper may then focus on providing hooks and features for various language tools (not just "sloppificator', but also static analyzers, code tranformations, checking interpreteres, etc.), leaving implementation of convenient editing mode to the community.

josephg

josephg commented on May 9, 2024

@josephg

Taking my first steps with zig at the moment, and immediately ran into this. How do people meaningfully iterate on code when the compiler complains any time what I'm writing isn't completed yet? Eg, I wrote this as a start to my program:

pub fn main() !void {
    var g = Graph.init(std.testing.allocator);
}

But my program won't compile. Do I need to delete some of my code (the var g) so I can test some other code, and then add it back again afterwards? Apparently I can't use _g like I can in rust, to assure the compiler that my variable is unused. Do I need to write a useless dummy function just so I can test things? (Eg fn drop(x) {}?)

This is a horrible experience.

And for what? To "force" me to "always write good code"? I'm not your wayward child. How utterly patronizing.

Beyley

Beyley commented on May 9, 2024

@Beyley

Do I need to delete some of my code (the var g) so I can test some other code, and then add it back again afterwards? Apparently I can't use _g like I can in rust, to assure the compiler that my variable is unused. Do I need to write a useless dummy function just so I can test things? (Eg fn drop(x) {}?)

No, you can use _ = g; for marking as "yes compiler i know its unused", and for mutability errors, just replace the var with const (there is _ = &g;, but its kind-of a hack, and you should probably just temporarily set it as const).

the first is done automatically by ZLS' autosave feature, but the second you have to do yourself

josephg

josephg commented on May 9, 2024

@josephg

Thanks - I just figured that out. (It took me a lot of searching to realise that was an option - it would be great if the compiler error suggested that as a fix).

the first is done automatically by ZLS' autosave feature

.. But, this is the worst of all worlds as far as this error goes. It means that I don't even get a compiler warning when I have unused variables. My code is silently "corrected" regardless of whether or not the fix matches my intent. If you're going to autofix code to suppress this error, zig may as well just turn the error off entirely.

rohlem

rohlem commented on May 9, 2024

@rohlem
Contributor

My code is silently "corrected" regardless of whether or not the fix matches my intent. If you're going to autofix code to suppress this error, zig may as well just turn the error off entirely.

@josephg Just to clarify, this is the reason why the Zig (core) toolchain has so-far taken a stance against automatic edits.
The mentioned "autofix" mechanism is an opt-in feature (configuration setting enable_autofix) of ZLS (which is community-maintained).
(I would assume the intent was that people would either immediately spot the autofixes, or re-read code after writing it to look for unintended uses of _ - I don't use it myself, so can't comment on efficiency one way or the other.)

josephg

josephg commented on May 9, 2024

@josephg

or re-read code after writing it to look for unintended uses of _

This is significantly worse than a compiler warning, but I can see how it ended up this way if zls is community maintained and has a different opinion about this issue than the zig compiler authors. Sorry for temporarily hijacking the thread - and thanks for the advice. I'll give that a whirl.

Nolan-O

Nolan-O commented on Feb 2, 2025

@Nolan-O

Even the linked YAGNI article specifically states:

Yagni only applies to capabilities built into the software to support a presumptive feature, it does not apply to effort to make the software easier to modify. Yagni is only a viable strategy if the code is easy to change, so expending effort on refactoring isn't a violation of yagni because refactoring makes the code more malleable.

YAGNI is at odds with treating temporary reductions of requirements as if they will be permanent. Making the compiler obtuse for the sake of providing friction when someone is caught not being so perfect in their planning that they avoided certain subsets of debug modifications is a bizarre philosophy. I'm not gonna need it? I literally will, as soon as I remove this early return which will exist for 1 compilation. The friction is ineffective. It will not stop me from having to make debug builds. It will not change the types of modifications I need to make for debugging.

Final point I want to make, the first priority of the Zig language design goals is the ability for a person to quickly and comprehensively peruse an unfamiliar codebase, and really understand it completely, holding it all in their head, confidently able to maintain it without worrying about unknown unknowns.

Using an unfamiliar codebase is precisely how I ending up here, the control flow mechanisms it uses are complex and only easily investigated at runtime. Additional friction with debug builds are doing the opposite of helping me quickly familiarize myself with the codebase.

rr-

rr- commented on Feb 11, 2025

@rr-

I agree with the other people. While clean code is important, expecting the compiler to act as a CI linter or a stand-in for code reviews is asking it to wear too many hats. A system that halts compilation over non-critical issues disrupts creative flow and discourages quick iteration. A more balanced strategy that issues warnings rather than flat-out errors would better support both productive coding and the spirit of exploration. It could still allow policing quality through additional flags or by treating them as errors for specific targets.

locked as resolved and limited conversation to collaborators on Feb 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @pjz@josephg@andrewrk@vi@marler8997

        Issue actions