Tag: Programming Languages

  • Elixir v1.20 makes gradual typing useful without annotations

    Elixir v1.20 makes gradual typing useful without annotations

    Elixir v1.20, released on June 3, 2026, turns gradual typing into a default compiler feature for every Elixir program. The important part is what it does not demand: teams do not need to add type annotations before the compiler can start finding dead code and type violations that would fail at runtime. The release team says the new checker passed 12 of 13 categories in the If T type-narrowing benchmark.

    The short version

    • Elixir v1.20 applies type inference and gradual type checking across every program, according to the official June 3, 2026 release post.
    • The release looks for “verified bugs,” meaning type violations where the accepted and supplied types are disjoint enough that runtime failure is guaranteed if the code executes.
    • The new dynamic() behavior narrows possible runtime types instead of throwing away type information the way many gradual systems do.
    • Elixir passed 12 of 13 categories in the If T type-narrowing benchmark cited by the release team.
    • The Hacker News discussion was excited about the type-system work, but much of the useful skepticism centered on Elixir’s learning curve, Phoenix macros, LiveView security habits, and BEAM concepts.

    What happened

    Elixir v1.20 is the first development milestone in the language team’s set-theoretic type-system plan. Jose Valim’s release post says every Elixir program is now gradually type checked without new type annotations, with the compiler using inference to find dead code and runtime-guaranteed type errors. That is a meaningful shift for a dynamic language that has historically leaned on pattern matching, guards, Dialyzer-style analysis, and runtime confidence rather than mandatory type signatures.

    The release also reports progress on type narrowing. Elixir v1.20 passed 12 of the 13 categories in the If T benchmark, a test suite focused on how well languages recover type information from ordinary control flow. That result matters because gradual typing is easy to sell in theory and hard to make pleasant in old codebases. A system that floods developers with false positives loses trust quickly.

    Why Elixir v1.20 is worth watching

    Elixir v1.20 is worth watching because it tries to make type checking useful before a project commits to a typed migration. The compiler behaves as if function arguments began as dynamic(), then narrows the possible range as code uses guards, pattern matches, conditionals, tuple checks, map-key checks, and standard-library calls. If a value might be an integer or a string, the compiler does not immediately reject every operation that accepts only one of those possibilities. It waits until the accepted type and the possible type no longer overlap.

    That design is more conservative than a strict static checker, but it fits the way many Elixir teams work. Existing Phoenix, OTP, and BEAM applications can upgrade and see which bugs the compiler now proves, without stopping the team for a large annotation project. For more IT and AI developer-tool coverage, see the IT & AI archive.

    What does Elixir v1.20 change for developers?

    Elixir v1.20 changes the default feedback loop for backend developers by moving some runtime failures into compile-time warnings. The June 2026 release gives examples where is_list, is_integer, is_map_key, tuple_size, case, and nil checks refine what the compiler knows. If a branch has already handled nil, the next branch can be checked as if the value is only the remaining type.

    The practical effect is not that Elixir suddenly becomes TypeScript or Rust. It is closer to a quiet compiler assistant that reads the shape of the code developers already write. That makes Elixir v1.20 especially interesting for teams that like the BEAM runtime and Phoenix ecosystem but still want earlier warnings for impossible calls, redundant clauses, and dead code before those paths reach production.

    How dynamic() avoids the usual gradual-typing trap

    The dynamic() type in Elixir v1.20 is not a polite spelling of “anything goes.” The release describes two properties: compatibility and narrowing. Compatibility means the compiler only reports a violation when the possible supplied type and the function’s accepted type are disjoint. Narrowing means the compiler keeps refining the possible type range as the program uses the value.

    A simple example from the release explains the difference. If a value can be either an integer or a binary, calling a function that accepts one of those types is not automatically an error. But passing the same value to a map-only function is a verified violation because neither integer nor binary overlaps with map. That choice trades aggressive warnings for developer trust. It will miss some questionable code, but the warnings it does produce should be harder to dismiss.

    What Hacker News readers are arguing about

    The Hacker News thread treated Elixir v1.20 as a serious language milestone, not a minor release-note item. The post drew more than 500 points and about 200 comments by June 4, 2026. The strongest positive thread was simple: gradual typing makes Elixir more attractive to developers who already like the BEAM model but hesitate because dynamic code can hide mistakes until production.

    The useful skepticism was less about the type system itself and more about adoption friction. Several commenters said Elixir and Phoenix can feel hard to learn because the ecosystem assumes familiarity with functional programming, OTP supervision, macros, optional parentheses, keyword lists, and LiveView’s security model. Others pushed back, pointing to ElixirForum, official guides, Elixir in Action, Erlang in Anger, Joy of Elixir, and the Phoenix LiveView security documentation as practical learning paths.

    The builder takeaway from that discussion is blunt: Elixir v1.20 improves compiler feedback, but it does not remove the need to learn the runtime model. Teams evaluating Elixir should test the new type checker on an existing service, then separately judge whether their team is comfortable with BEAM processes, supervision trees, Phoenix macros, and LiveView authorization patterns.

    The practical read

    Elixir v1.20 is not the release where Elixir gets user-written type signatures everywhere. The official post says typed struct definitions and broader type signatures still depend on more work around performance, recursive types, parametric types, and efficient traversal of map key-value pairs. Treat this release as the compiler starting to earn trust, not as the final typed-Elixir destination.

    For current Elixir teams, the obvious move is to upgrade a non-critical service first and read the new warnings with care. The warnings should identify code that is dead, redundant, or guaranteed to fail if reached. For teams outside the ecosystem, Elixir v1.20 is a reason to revisit the language if gradual typing was the missing piece. It is not a reason to ignore the learning curve. The runtime and framework model still matter as much as the new checker.

    Sources

  • Zig build system cuts help startup from 150ms to 14.3ms

    Zig build system cuts help startup from 150ms to 14.3ms

    The Zig build system has been split into two jobs: a small configuration step and a faster execution step. Andrew Kelley says the change cut zig build --help from 150ms to 14.3ms on the benchmark in Zig’s 2026 devlog, mostly by avoiding repeated work when the build graph has not changed.

    The short version

    • Zig now separates the configurer, which runs build.zig, from the maker, which executes the serialized build graph.
    • The benchmarked zig build --help path dropped from 150ms to 14.3ms, with CPU cycles down from 593M to 24.1M.
    • The Zig build system can reuse a cached binary configuration file when command-line changes do not alter the build graph.
    • Most build APIs remain compatible, but code that inspected b.args needs to move to addPassthruArgs().
    • The practical payoff is less waiting in watch mode, editor integrations, help output, and other small commands that developers run over and over.

    What happened

    Before this rework, a project’s build.zig file and Zig’s build runner implementation were compiled into one large Debug-mode process. The build script created a graph in memory, and the same combined process ran it.

    The new Zig build system splits that path. The configurer compiles and runs the user’s build.zig logic, then writes the resulting build graph as a binary configuration file. The parent zig build process can cache that file for later runs.

    Execution moves to the maker. Zig compiles the maker in Release mode, does that compilation asynchronously, and stores it in a global cache per Zig version. Once the cached config file and maker are ready, the maker executes the graph.

    That is a small architectural change with a very concrete point: editing a tiny build script should not force Zig to rebuild the whole build system machinery every time.

    Why this is worth watching

    The headline number is narrow but useful. Zig’s devlog says zig build --help fell from 150ms to 14.3ms in average wall time, a 90.4% reduction. CPU cycles fell 95.9%, instructions fell 95.6%, and cache references fell 94.3%.

    A help command is not the same thing as a full project build. Still, build tools spend a lot of time on short-lived commands: printing help, checking options, restarting watch mode, serving a web UI, or feeding data to an editor. Those are exactly the places where 100ms delays become noticeable.

    The cached configuration also means some command-line changes no longer force build.zig to run again. The devlog gives -freference-trace as an example: if the build graph does not change, Zig can reuse the previous configuration.

    For more developer tooling coverage, see the IT & AI archive.

    What changes for Zig build system users

    The rework is not meant to break most build scripts. The visible compatibility issue is passthrough arguments. Code that directly observed b.args and forwarded it with run_cmd.addArgs(args) now needs to use run_cmd.addPassthruArgs().

    That does remove one bit of observability from the build script. In return, changing those passthrough arguments no longer has to invalidate and rebuild the configuration step from source. It is the kind of trade that makes sense for a build tool: give up a rarely needed hook to make the common path cheaper.

    Zig 0.17.0 is expected within weeks, according to the devlog. Teams already using development builds should search for b.args patterns before upgrading. Everyone else can treat this as an early warning rather than a fire drill.

    What Hacker News readers are arguing about

    The Hacker News thread is less about the specific 150ms benchmark and more about whether Zig is becoming practical enough to use before 1.0.

    One camp is clearly encouraged. Several commenters said recent Zig releases have been disruptive but worth it, especially around I/O design and the feeling that Zig works well as a small tooling language. The recurring praise is not that Zig is magically faster everywhere. It is that the language feels good for low-level experiments without forcing as much ceremony as C++ or Rust.

    The skeptical side is also useful. Some readers pushed back on claims that the new I/O system is already highly efficient, pointing to dynamic dispatch, vtable indirection, and unresolved questions around async behavior. Others said they like Zig but are tired of release-to-release API churn and may wait for 1.0 before using it in serious projects.

    The build system change fits that split. It is a strong piece of engineering, but it lands in a language that is still moving quickly. If your project values stable tooling above all else, the number to watch is not 14.3ms. It is how much your build script changes between Zig releases.

    The practical read

    The Zig build system rework is worth watching because it attacks a boring part of developer experience that compounds all day. Fast compilers help, but fast tool startup matters too. If a build tool is called by editors, shells, watch processes, and documentation commands, every avoidable rebuild is a tax.

    For Zig users, the immediate task is simple: test development builds if you can, check for b.args, and read the 0.17.0 release notes when they land. For people building other developer tools, the design lesson is broader. Separate user configuration from execution, cache the serialized result, and make the hot path cheap enough that users stop noticing it.

    Sources

  • Zig interview: Andrew Kelley on the long road to 1.0

    Zig interview: Andrew Kelley on the long road to 1.0

    The Zig interview with Andrew Kelley is useful because it treats a programming language as more than syntax. Kelley talks through why Zig is still pre-1.0, why the project bans AI-generated issues and pull requests, and why build tooling may matter as much as language design for systems programmers.

    The short version

    • Kelley frames Zig as a systems language for programmers who still want direct control over memory, allocators, and hardware costs.
    • The project is taking its time before 1.0 because Kelley sees that label as a backward-compatibility promise, not a marketing milestone.
    • Zig’s no-AI contribution policy is mostly about maintainer time. If a contributor cannot explain the patch, review becomes unpaid cleanup.
    • The move from GitHub to Codeberg came down to working project infrastructure, especially CI reliability.
    • For more developer-tool coverage, see the IT & AI archive.

    What happened in the Zig interview

    JetBrains published a long video interview with Andrew Kelley, the creator of Zig. The conversation covers the language’s origin, its relationship to C, C++, Rust, and Go, the Zig Software Foundation, the move from GitHub to Codeberg, and the project’s policy against AI-generated issues and pull requests.

    The most concrete thread is the build story. Kelley argues that a good project should not require every new contributor to install a different stack of platform tools or recreate a Docker setup before the first compile. Zig’s pitch is that zig build should make cross-compilation and dependency handling feel boring, even when the target operating system or architecture is different from the developer’s machine.

    The interview also gives a clearer reason for the slow march toward Zig 1.0. Kelley treats 1.0 as a compatibility contract. Once the project makes that promise, bad language and standard-library decisions become much harder to undo.

    Why this is worth watching

    The Zig interview lands at an awkward moment for systems programming. C is still everywhere because it is stable, portable, and close to the machine. Rust has pushed safety and ownership into the mainstream, but it asks developers to buy into a stronger type system and a more opinionated model of correctness. Zig is trying to live in the middle: less hand-holding than Rust, more explicit guardrails and tooling than C.

    That bet only works if the toolchain feels excellent. A language can be elegant and still lose developers at the first broken build. This is why the build system, cross-compilation, and package story matter so much. Zig is competing on the whole workflow, not only on what individual functions look like.

    The governance piece is just as interesting. Kelley describes the Zig Software Foundation as a 501(c)(3) nonprofit with roughly $670,000 in 2024 income. That structure does not make the project immune to money pressure, but it changes the incentives. There is no obvious acquisition path to serve, and no single corporate owner gets to decide the language’s direction by default.

    What Hacker News readers are arguing about

    The Hacker News thread is small, but the split is clear. Supporters like the patience. They read Kelley’s approach as a rare case of a language project trying to get the foundation right before locking compatibility for years.

    The sharper objection is about time. One commenter argues that Zig has already spent about a decade changing the design and still has no obvious path to the stability that made C so durable. That is a fair worry. If a language wants to become a C alternative, stability is not a nice extra. It is part of the product.

    Other replies push back by saying Zig needs to break things now if it wants to barely change later. That is the strongest defense of the project, and also the biggest risk. The strategy only looks wise if Zig reaches a stable version with enough momentum left for serious adoption.

    The AI angle gets less debate in the thread than the title might suggest. The practical point is still clear: small open-source teams are not only reviewing code. They are reviewing the contributor’s understanding. AI-generated patches can make that job slower when the author cannot defend the change.

    The practical read

    For developers choosing tools today, Zig is worth testing where build friction hurts: command-line tools, cross-platform libraries, embedded targets, WebAssembly, or C interop. The language is not a safe default for every production team yet, especially if long-term API stability matters more than toolchain experiments.

    For maintainers, the no-AI rule is the more portable lesson. A blanket ban may be too strict for many projects, but the underlying standard is reasonable: contributors should understand what they submit. If review turns into explaining machine-written code back to its own author, the project is paying for someone else’s shortcut.

    For app and developer-tool builders, Zig is also a reminder that discovery is not only about the language homepage. Build commands, package defaults, editor support, CI behavior, and repository hosting all shape whether a tool gets adopted. That is the part of the Zig interview I would watch most closely.

    Sources