Fortran vs Rust vs Zig

This lesson answers the two questions everyone asks about a 65-year-old language: is Fortran a system language? and why would I choose it over Rust or Zig? The honest answer to both is a landscape, not a verdict: each language targets different guarantees, and the same project often needs two of them. Here is the map.

Is Fortran a system language?

No — and the distinction is precise and useful. A systems language in the modern sense is one built to write operating systems, kernels, device drivers, browsers, embedded firmware and security infrastructure: it must provide manual memory control, small runtime, predictable machine-level behaviour, and (increasingly) compile-time memory safety. That world belongs to C, C++, Rust and Zig. Fortran was designed for formula translation: dense arithmetic over arrays, compiled to machine code as fast as the compiler can manage.

Three facts mark the boundary honestly:

  • It compiles to native code and runs bare-metal fast — that part of "systems" it shares. On pure array numerics it often beats C, because whole-array expressions plus the no-aliasing rule give the optimizer more room.
  • It has no memory-safety guarantees. Buffers can overflow, pointers can dangle. Fortran catches many classes with -fcheck=bounds, but nothing enforces safety at compile time the way Rust's borrow checker does.
  • Its ecosystem ignores systems territory. Nobody builds kernels, drivers or embedded firmware in Fortran; the tools, CRT bindings and libraries for that work simply are not there.

Conclusion: Fortran is best described as a high-performance numerical/scientific language, close to the metal in its own domain, not a general-purpose systems language. Choosing it for HPC kernels is correct; choosing it to write an OS would be a category error. The comparison page's landscape figure summarizes the positions.

Positioning map of C, C++, Rust, Zig, Python and Fortran

Fig. 1 — Languages aim at different axes; Fortran owns the far numerical end.

Head-to-head: Fortran, Rust, Zig

The table below compares by the properties engineers actually choose on. "Guarantee" means what the language promises at compile time; the last row is where Fortran is decisively different from both.

PropertyFortran (2023)RustZig
Born / decade1957, revised continuously20152016
Primary domainnumerics, HPC, simulationsystems, safe infrastructuresystems, C replacement
Memory safetynone enforced at compile timeguaranteed (borrow checker)opt-in safety, allocators explicit
Whole-array mathnative (A = B + C)via iterators/manual loops + cratesmanual loops
SIMD/vectorizationcompiler-driven, standardstd::simd/autovectorization improvingexplicit, low-level
Parallelism, standard-levelcoarrays + do concurrentthreads/std + rayon (lib)threads + std, manual
Distributed HPC (MPI)native binding, century of practicersmpi (thin binding)manual FFI
Compile-time metaprogramminglimited (generics, preprocessor)macros (powerful)comptime (unique)
Interop with Ciso_c_binding, ABI-standardextern "C", cbindgen@cImport, first-class
Ecosystem maturity in numericsBLAS/LAPACK/netCDF/HDF5, 50 yearsyoung (nalgebra, ndarray)very young
When to reach for itthe hot kernel, the sim, the solverthe service, the parser, the security boundarythe driver, the embed, the C interop layer

What Rust and Zig give up for numerics

Rust's safety and Zig's control are real and valuable — nobody recommends Fortran for a network daemon. But in the numerical arena, each pays a price Fortran visitors notice immediately:

  • Rust and arrays: whole-array expressions are not part of the language. a[i] = b[i] + c[i] loops are written by hand or via iterators; the optimizer recovers much of it, but the expression is the loop and the loop is yours to write and maintain. SIMD arrives via unstable std::simd or crates, not via a -O3 flag.
  • Zig and vectors: Zig gives explicit control of memory and comptime code generation — superb for allocators and kernels — but array math stays manual, and HPC libraries (BLAS/LAPACK/MPI bindings) are near-zero. You would build the wheel before the physics.
  • Both and aliasing: Rust's aliasing rules are powerful but you pay for them with verbosity in numerical code (raw pointers, unsafe blocks, iterator gymnastics); Zig's default is C-like aliasing that still forces the optimizer's hand less than Fortran's no-alias default.

None of this is a failure of Rust or Zig — they chose different guarantees. The point for you as an engineer is to not make one language carry the whole product if the product has two very different ends.

The hybrid: Fortran kernels inside a modern system

The interop lesson's ABI is the bridge that makes the either/or disappear. A realistic modern stack: Rust or Go service owns the API, auth, orchestration; Fortran shared library compiled with bind(c) owns the physics; Python wires experiments and models on top. Each layer uses the language it cannot be replaced in, and the C ABI (or f2py) is the only glue. The python-interop lesson demonstrated the same pattern from the Python side; the interop demo shows the raw bind(c) symbol table.

# the build that produces the cross-language kernel library
gfortran -c -O3 -fPIC physics.f90
gfortran -shared -o libphysics.so physics.o
# Rust service: extern { fn solve(...); }   Zig: @cImport libphysics.so

Picking the right side

Decision rules distilled from the whole lesson:

  • Floating-point-heavy, array-shaped, cluster-bound → Fortran (with OpenMP/MPI/coarrays as the terrain allows).
  • Systems component, security-critical, massive concurrency → Rust.
  • Embedded, allocator-level control, C ecosystem drop-in → Zig.
  • Mixed product → ship the kernel as a library and host it anywhere the target demands.

The honest closing note: language loyalty is cheap, performance is priced in physics, and the best engineers in this field read the guarantees, measure, and pick without ideological baggage.