Back to JetBrains

Programming Languages Today and Tomorrow

JetBrainsAugust 22, 20261h 26m
In a Nutshell

Programming languages are defined by their core ideas and safety bets rather than syntax, with memory safety and capability systems becoming critical as AI generates un-reviewable code. Rust's static borrow checking, Scala's capability tracking via the caret operator, and experimental approaches like Field C represent different tradeoffs between performance and exploit prevention. The industry is seeing widespread rewrites into safer languages, with gradual typing and compiler-enforced safety mechanisms replacing manual code review as the primary defense against LLM-generated vulnerabilities.

AI-Generated Notes

These notes were generated by AI and may contain inaccuracies.

Vital Bragillski, Head of Rust Ecosystem at JetBrains, delivered this lecture at PAS programming camp. His background includes first exposure to coding in 1992 with BASIC at a youth community center, where he dropped out after struggling with arrays. He later found a book covering FORTRAN, Pascal, and BASIC, studying it for a year and a half without a computer by writing programs on paper.

His formal education included learning multiple programming languages including Perl, PHP, JavaScript, Java, C, and Object Pascal. Starting around 2000, he taught at universities, delivering full courses or lectures on more than 20 programming languages. Around 2005, he began working with Haskell and later became a member of the Glasgow Haskell Compiler steering committee, authoring "Haskell in Depth" published five years ago.

From 2008, he studied programming language theory, focusing on lambda calculus and proof assistants including Rocq (formerly Coq) and Lean. Since 2022, he has served as Rust Developer Advocate before becoming Head of Rust Ecosystem at JetBrains, and since June has been a member of the Rust Commercial Network steering committee.

The lecture focuses on five main topics: the caret/circumflex/hat operator symbol, the concept of capability, safety in programming languages, LLMs, and people. The speaker emphasizes that ideas behind programming languages matter more than syntax or semantics, as ideas encompass properties, principles, and goals that language developers aim to achieve.

Beyond syntax and semantics, programming languages require tooling ecosystems including compilers and package managers, governance structures determining which features are included or excluded, and community dynamics that influence language development.

The speaker presented several language-defining ideas for identification:

  • C++: "Zero overhead abstractions" - the principle that building abstractions like classes and templates incurs no runtime performance penalty unless used

  • Java: "Write once, run anywhere" - the 1995 motto, though noted as less accurate with modern platforms like WebAssembly

  • Kotlin: "Concise, multi-platform, fun" - concise compared to Java, targets iOS and WebAssembly, with "fun" referencing both the function keyword and the enjoyable development experience

  • Zig: "No hidden control flow, no hidden memory allocations, no preprocessor, no macros" - defines itself through absence of features like exceptions, which represent hidden control flow

  • Scala: "A mostly functional, richly typed language that combines safety and convenience" - taken from Martin Odersky's talk from one year ago

  • OCaml: Also matches the Scala description closely

  • Roc: "Fast, friendly, functional" - a new language by Richard Feldman, author of Elm, with release 0.1.0 planned for the current week. Features amazing hot reload, is a singly-paradigm functional language

Every programming language represents a set of bets about which ideas matter most. The 2009 meme about how programming language communities perceive themselves and others illustrates deep concepts behind language identities, with the Haskell column being notably accurate.

A clear industry trend shows movement from dynamic to static typing for safety. Dynamic languages offer flexibility but lack the safety provided by types. Gradual typing allows mixing dynamically and statically typed code within the same codebase, seen in Python with multiple typing tools and TypeScript as a gradually typed wrapper over JavaScript.

The caret/circumflex/hat symbol has numerous uses across languages including XOR operations, pointer types, power operators, and regex negation. The symbol's meaning cannot be assumed when encountered in new languages.

C++26 introduces reflection using the "cat ears" operator (^^). The implementation uses experimental/meta headers and allows compile-time computation via constexpr expressions. Code can introspect types using ^^ to access metadata about structures, retrieve non-static data members, and create static arrays of member information. Template for loops enable compile-time iteration over this metadata.

Reflection addresses C++'s meta-programming needs, replacing problematic C preprocessor macros (textual substitution lacking type safety) and complex template meta-programming (slow compilation, cryptic error messages). Constexpr provides better approaches but limited introspection capabilities.

Philip Panteleev, creator of the Phil-C compiler project (two years old), provided a definition at the Software Should Work conference: in a memory-safe programming language, memory logic bugs don't give attackers control over all of memory. Memory safety concerns exploitability rather than eliminating all memory logic bugs, which is impossible. The goal is preventing attackers from gaining read/write access to other memory regions through buffer overruns, use-after-free, or double-free vulnerabilities.

In July, Andrew Kelly, creator of the Zeke programming language and prominent figure in the programming language community, opened an issue on the Zeke repository on Codeberg about adding a memory-safe compilation mode unlike Rust. This sparked significant tension in the programming language community, with questions about whether the phrasing implied Rust was not memory safe. Comments appeared on the issue and social media, with some claiming Andrew Kelly was crazy and hated Rust because he had recently rewritten a JavaScript runtime from Zeke to Rust.

The actual question became what memory safety means and whether Rust meets certain definitions of it. The discussion highlighted how people have different understandings of the term memory safety, with some interpretations being entirely different from others. The discussion became so heated that Andrew Kelly wrote that if you don't have Zeke repos on this website or if you are not Philip Pasler, your opinion does not matter in this discussion. The thread was eventually blocked due to the intensity, and the issue name was edited four times, with the final version being: introduce a fully memory safe no escape hatches like in Rust compilation mode inspired by Field C.

Rust uses static borrow checking that enforces ownership at compile time. Every piece of memory is owned by some variable, and it is nearly impossible to have two variables own the same memory. When a variable goes out of scope, the memory automatically returns to the operating system or memory manager, eliminating the need for garbage collection or explicit freeing instructions.

Rust allows unsafe code for foreign function interfaces with C and C++ libraries. Unsafe blocks allow bypassing some checks, and certain data structure implementations require unsafe blocks because it is impossible to prove certain things to the borrow checker. The nature of static analysis makes 100% correctness impossible due to theoretical uncomputability, requiring unsafe blocks as a compromise.

Zeke offers several compilation modes, including a safe compilation mode that introduces runtime checks for every pointer operation. This approach is slower due to conditional operators checking memory correctness on each access. Without the safe compilation mode, developers must write all safety checks explicitly, which is difficult and prone to mistakes.

Philip Pasler developed the Field C approach using invisible capabilities for runtime tracking of pointer operations. For every pointer allocation, additional memory fields are added containing upper and lower memory addresses, defining the valid access range. Every memory access reads these fields and verifies correctness, making the program unexploitable. When violations occur, the program panics rather than allowing attacker access to memory.

The implementation adds passes to LLVM, allowing any C or C++ code to be compiled with these safety guarantees. Field C is a compiler modification rather than a new programming language, making existing C and C++ codebases memory safe. However, some older C programs that store memory addresses as integer variables rather than pointers present challenges for this approach.

Philip Pasler demonstrated compiling LibreOffice, a massive codebase, using Field C with almost no modifications. This illustrates the fundamental tradeoff between safety and performance: safety requires accepting reduced performance, while maximum performance typically sacrifices safety guarantees.

The TypeScript compiler was recently rewritten in Go rather than Rust. Anders Hejlsberg, known for Turbo Pascal, C#, and TypeScript, explained the choice in a recent interview. The decision was driven by convenience - TypeScript has many circular structures that are complicated to implement in Rust due to borrow checker requirements. The team prioritized the performance benefits of native language compilation over the complexity of satisfying Rust's borrow checker, accepting Go's garbage collection as a reasonable trade-off.

Capabilities originated in a 1962 paper describing a system using code words with additional information. The term capability was introduced in 1966 by Dennis and Van Horn. A capability is an unforgeable token that grants access to resources, which can include memory, devices, network sockets, CPU, or GPU resources.

Capabilities represent one of two main approaches to security systems, alongside access control lists (ACLs). ACLs work through username-permission lists, as used in Linux and macOS. Capabilities work by possessing tokens that prove permission, potentially using cryptographic techniques to create unforgeable tokens.

Capabilities are unforgeable, composable (multiple tokens can be combined), and transferable. The invisible capabilities concept from Field C represents one implementation, adding metadata to data that enables access verification.

Scala implements capabilities using a caret or circumflex operator. Functions can require capabilities through using parameters, such as a file system capability for file operations. Return types can capture capabilities, meaning the returned values carry the capability requirements.

When assigning values, the compiler checks capability compatibility. Assigning a capability-requiring result to a variable with minimal or no capabilities produces a compilation error, preventing capability escape to contexts where it is not expected.

Without capture checking, values can silently escape with their capabilities, potentially leaking file handles or database connections. Capture checking gives the compiler tools to prevent such leaks and disallow unauthorized operations.

Martin Odersky, Scala's designer, gave a talk in October of last year titled Where are we with Scala's capabilities? providing detailed information about this system.

In May, Martin Odersky published a paper called tracking capabilities for safer agents, exploring how capabilities can provide guarantees for AI agents. The paper addresses preventing agents from performing unauthorized actions through agentic harnesses that define allowed operations like shell access, database connections, API keys, or file system access.

The compiler can enforce capability discipline by expressing what each function is allowed to access through capability-typed functions. Programs violating contracts are rejected by the type checker at compile time, preventing runtime surprises.

This approach envisions using strict compilers as agentic harnesses, where agent tools become typed resources rather than simple function calls. Capability safety ensures no resource leaks or runtime exploits. Stricter languages like Rust with borrow checking or Scala with capability checking provide more runtime control, making them potentially safer choices in the age of LLM-generated code.

It is impossible to read and review all AI-generated code. The volume of generated code exceeds human review capacity, meaning unreviewed code will reach production. Safe languages with strict harnesses become essential, with compilers providing a foundational level of protection. Scala capabilities represent one approach, with future developments likely including additional safety mechanisms.

Rust development involves two main bodies. The Rust project consists of individuals working on the compiler, standard library, and tooling, organized into teams with a leadership council. Anyone demonstrating dedication and knowledge can join and contribute to Rust development.

The Rust Foundation is an independent nonprofit organization. Membership requires payment, with different tiers including platinum members like AWS, Google, Microsoft, Meta, and Huawei. JetBrains is also a member at a smaller level. The Foundation has a board of directors with representatives from both members and the Rust project.

The Rust Foundation does not control language design or tooling decisions, which remain with the Rust project. The Foundation handles practical matters difficult for open source maintainers, such as operating crates.io, paying for GitHub Actions, and other development resources.

The Rust Commercial Network was recently created to address adoption barriers. Unlike the Rust Foundation's paid membership model, the Commercial Network is open to companies, the project, other open source projects, and individuals. The network identifies blockers in the language, compiler, or tooling that prevent Rust adoption through regular online meetings.

The next meeting is scheduled for August 31. The network facilitates initiatives that may lead to working groups, interest groups, or consortiums in specific areas. A fully functional network services working group currently meets regularly to discuss problems with async code and network services, and to identify funding for necessary development work.

The Commercial Network also works on funding connections between maintainers needing financial support and companies with resources to provide it.

Beyond formal governance structures, Rust has an active community including conferences, local meetup groups worldwide, a Discord server, and Zulip as the primary communication platform for Rust development. The Rust language Zulip chat at rust-lang.zulipchat.com is essential for language design participation and observing how decisions are made.

GitHub serves as the development hub where the compiler source code, issues, and pull requests are located. The principle that open source development involves people choosing to participate at the right time and place remains central to language development.

A single person can make a difference in programming language development. Most programming languages are developed openly, allowing anyone to contribute meaningfully. Participation in developing programming languages, whether Rust, Haskell, or other languages, represents both an enjoyable and valuable activity.

The speaker encourages developers to join communities around various programming languages including Ras, Haskell, Scala, C++, and Kotlin, emphasizing that participation in these communities is enjoyable and valuable.

Several notable projects and developments are highlighted as observations from the current programming language landscape, though not intended as comprehensive coverage of all ongoing activity.

A current trend involves taking existing tools and rewriting them in different programming languages or using different technologies. This approach has demonstrated significant benefits in performance and safety.

UV is a tool that has reimagined the Python community by implementing a package manager in Rust instead of Python. Charlie Marsh, the developer behind UV, created a fundamentally faster alternative to existing Python tooling. The performance improvements are substantial - installing new dependencies for Python projects is now significantly faster, making it excellent for CI/CD pipelines, AI agents, and general development workflows. The company behind UV, Astral, was recently acquired by OpenAI, meaning OpenAI now owns Python package management.

Bun represents another significant rewrite project by Jared SA, who used LLMs to rewrite it from Zig to Rust. While some view this as an advertising campaign for Anthropic (since Bun belongs to Anthropic), the project demonstrates the feasibility of using AI agents for large-scale code rewrites. The topic remains prominent in social media discussions.

The Go TypeScript compiler was rewritten from JavaScript to Go through manual effort without using LLMs. This project demonstrates that rewrites result in faster and safer implementations.

Kotlin LLM is a research project from July 2026 that introduces smart macros for Kotlin development. The approach allows developers to place LLM macros in their codebase with instructions, and during compilation the LLM converts these descriptions into type-checked Kotlin code that gets committed to the repository. This uses LLMs once during development rather than at runtime, with the generated code becoming permanent part of the codebase.

Java remains extremely important for industry and software development. Three major projects have been ongoing for many years: Loom, Valhalla, and Panama. These projects demonstrate how an over-30-year-old language can be reshaped with modern capabilities. The implementation process involves years of proposals, refinements, and implementations, with components gradually appearing in new Java versions.

Project Panama is highlighted as particularly significant, bringing Java much closer to C and native code, significantly improving performance and interoperability between Java and the native world.

C# 15 introduces discriminated unions, implementing algebraic data types - a concept known since the 1970s. While Kotlin, Scala, Swift, Rust, and Pascal have had versions of this feature, C# now brings this functional programming concept to mainstream adoption. The implementation approach is considered well-executed for bringing new features to an established language.

Codespeak is a project by Andre Breslav, the original designer of Kotlin. The project reimagines software development by acknowledging that code review has become impossible at scale. Instead, developers use high-level specifications on top of their codebase, with LLMs translating these specifications into actual code. This allows programmers to express intent in natural language while LLMs handle implementation details.

Several key takeaways emerge from the discussion:

  • Programming languages are constantly evolving and never die
  • The AI code generation world requires more automatic safety mechanisms rather than manual review, since comprehensive human review is impossible
  • Safety measures come with performance costs that must be accepted
  • Programming language development is an open community that welcomes participation, which can be pursued as a hobby or career
  • The caret/circumflex/hat operator symbol has interesting potential applications

When asked why ideas are adopted so slowly in enterprise-focused languages, the response explains that some ideas may not be needed in their original time or context. Historical examples include lambda functions, known since the 1930s but only added to Java in 2018, and garbage collection, first implemented for Lisp in the 1950s with Java being the first mainstream language to adopt it. Programming language designers should study historical languages as good ideas may become relevant later. Esoteric language features may eventually become mainstream in 50 years.

Regarding difficulty with syntax where types appear after arguments or variables, the response acknowledges this as a common struggle. LLMs provide a solution by handling syntax generation, eliminating the need for developers to manually manage complex syntax. The speaker mentions personal difficulty with Scala syntax despite 15 years of exposure, finding the combination of parentheses, brackets, and symbols particularly challenging.

Keep JetBrains in your library

Save the videos and channels worth coming back to, and find them again in one place.