Any time I use an AI tool for something I’m deeply familiar with, I find a continual stream of mistakes and inconsistencies. When I use it on a topic I don’t know… everything sounds plausible and I don’t find mistakes. The difference worries me, and sounds a lot like the Gell-Mann Amnesia effect . AI can write confidently on any topic, with good presentation, just like newspaper articles. I find…
I spend a lot of time reviewing code, and I think it’d be easier if I saw more tastefully broken commits. Commits construct a story about a change: “first this happened, then that, that another thing” is a good narrative; “first everything happened, the end”… not so much. Sometimes, telling that story is impossible without having a commit that breaks tests or doesn’t compile! The principle that…
SQL databases support multi-column indices, where a single index can incorporate data from multiple columns. These are powerful, but the order of the columns matters, with differences observable in practice: there can be orders of magnitude between two similar & simple queries, depending on which uses a prefix of the index columns. Why does this limitation exist? Can we have a mental model for the…
When I use an AI coding agent to make a plan, I make a habit of opening that plan in my editor and then leaving inline comments with questions, requests and corrections directly in the file. The agent seems to be happy enough to work with these, and I find it gives better results than reading the plan in the agent and using chat to give feedback. By being a habit, it keeps me honest and stops me…
The Magit package for Emacs is my Git UI of choice, and git worktrees are very convenient. They mesh up particularly well by adding the built-in magit-insert-worktrees to magit-status-sections-hook . With this, the magit status buffer shows a summary of the branch/HEAD/path of all worktrees, and allow jumping between them in a flash. 1 2 ;; Show all worktrees at the end of the status buffer (if…
The TypeScript compiler options strictNullChecks and noImplicitAny interact in a strange way: enabling just strictNullChecks leads to type errors that disappear after enabling noImplicitAny too, meaning getting stricter has fewer errors! This is a low-consequence curiosity, but I did trip over it in the real world, while updating some modules at work to be stricter. The context TypeScript is a…
I occasionally add context instructions to an AI tool, but then am not sure whether those changes were picked up by the tool. The fun way to debug this is to add “Always speak like a pirate” to the instructions. This works in all tools. Context engineering! Context I use LLM tools like Claude Code. These come with the ability to customise the context fed to the model with files like…
I’ve noticed different people seem to use the word “deprecating” to mean two different things, when it comes to code and/or features: either removing entirely, or discouraging its use. I think it’s useful to have specific labels for both of these of concepts, so that communication is clearer. When you want to discourage new users of some existing code/feature, and… existing users continue working…
The network tab of a browser’s developer tools shows a list of requests. Sometimes there’s a problem with one of those requests! Maybe the server is crashing and returning a 500 error, or maybe there’s an unexpected 403 permission error. The dev tools UIs provide one-click “Copy as cURL” functionality to conveniently extract an executable ‘replay’ of the request, and it can be easily edited. This…
Hitting a bug is no fun: maybe it interferes with your work or play, or maybe it means you have to dive down a debugging rabbit hole. Remotely debugging a bug someone else has found is even less fun… I’ve settled on using a shell script for sharing executable self-contained reproducers for issues I find in software libraries and developer tools, to get help faster. Sometimes, when I’ve found an…
Rust’s match statement can do a lot of things, even C-style fallthough to the next branch, despite having no real support for it. It turns out to be a “shallow” feature, where the C to Rust translation is easily done, without needing to understand the code itself. The hardest part is coming to terms with writing it, and then convincing someone else to let you land it! Here’s what the tail handling…
The conventional units for expressing the mileage of an electric vehicle, like Wh/km (“watt-hours per kilometer”), are dimensionally equivalent to force, N (“newtons”). It seems this has a useful physical interpretation, and we can do some rough predictive calculations by estimating the drag and rolling resistance forces that align to real-world observed efficiencies. We recently got a battery…
Shell scripts sometimes have to append data to a file. Redirecting output with >> is the conventional way and works fine, but using tee -a instead is a usually better default, especially in continuous integration. It’s just as easy and gives automatic introspection : the same value is printed to stdout and so appears in normal logs too. 1 2 3 4 # conventional approach (worse!): echo…
Memory mapping a file for reading sounds nice: turn inconvenient read calls and manual buffering into just simple indexing of a memory… but it does blocking IO under the hood, turn a &[u8] byte arrays into an async hazard and making “concurrent” async code actually run sequentially! Code affected likely runs slower, underutilises machine resources, and has undesirable latency spikes. I’ve done…
GitHub offers permalinks to versions of files and lines, within a repository. They’re easy to create ( y keyboard shortcut) and have some nifty affordances like displaying a preview, plus they don’t become invalid as code changes. Use them! The permalinks use the commit hash of a particular version of the file, and thus the contents never changes, because they’re content-addressed and permanent 0…
Encoding data in decimal requires many more characters than the same data encoded in base64— 06513249 vs YWJj —but using decimal is better when stored in a QR code. The magic of QR modes means all those extra digits are stored efficiently, almost as though there was no encoding at all. Decimal encoding makes for QR codes that store more data , or are easier to scan . In this post, we’ll see: how…
Governments here in Australia have been telling us to keep distance from each other. Surprisingly, the same government has simultaneously put out posters that required people to get close, unnecessarily. They contain QR codes for contact-tracing check-ins that are small and dense, meaning they’re hard to scan. How could they be better? Here’s how: Three pages placed horizontally. They all contain…
Error correction sounds good. It means fewer errors, right? When it comes to QR codes, that’ll mean easier scanning for people, surely? It seems like that’s not the whole story. I wondered about this, and couldn’t find an answer, so I did some exploration, and found there’s two factors in tension: the error correction on one hand, and the resulting data density on the other: For fixed data, like a…
Taking shortcuts? Leaving edge-cases unconsidered and unhandled? Is this engineering?! My approach to programming and software engineering has been shaped by years of building open source compilers and libraries , where those edge cases matter, reliability is crucial and flexibility is important. It’s been a breath of fresh air to take a step back and stop thinking about every detail, and instead…
It’s glorious to work on one task at a time, to be able to take it from start to finish completely, and then move onto the next one. Sounds great, but reality is messier than that and context switches are common. Doing so can be annoying and inefficient, but not switching means tasks and colleagues are delayed. I combine git worktrees and pyenv (and plugins) to reduce the overhead of a context…
The primitive integer types supported by CPUs are finite approximations to the infinite set of integers we’re all used to. This approximation breaks down and some computations will give results that don’t match real integers, like 255_u8 + 1 == 0 . Often, this mismatch is something the programmer didn’t think about, and thus can easily result in bugs. Rust is a programming language designed to…
Memory unsafety and memory leaks are arguably the two categories of bugs that have received the most attention for prevention and mitigation. As their names suggest, they are in the same part of “bug space”, however they are in some ways diametric opposites, and solving one does not solve the other. The widespread use of memory-safe managed languages hammers this point home: they avoid some memory…
Imagine being able to step forward and backwards as code runs in your debugger. Imagine being able to do an test run multiple times with exactly the same sequence of instructions and values, right down to memory addresses and IO. Imagine being able to run an executable thousands of times and then do all that in the one execution that triggers the rare bug that’s draining you of life… The rr tool…
I recently released version 0.3 of my simple_parallel crate, which builds on Aaron Turon’s crossbeam to resolve the stability and safety difficulties : the crate now works with Rust 1.3.0 stable, and offers safe data-parallel for loops and map s. I still don’t recommend it for general use, but I think it’s a neat demonstration of what Rust’s type system allows, and hopefully inspiration for…
A new scheme for SIMD in Rust is available in the latest nightly compilers, fresh off the builders (get it while it’s hot!). For the last two months, I’ve been interning at Mozilla Research, working on improving the state of SIMD parallelism in Rust : exposing more CPU instructions in the compiler, and an in-progress library that provides a mostly-safe but low-level interface to that core…
I’m currently in San Francisco doing an internship at Mozilla Research, working on creating functionality for SIMD in the Rust programming language. (This post is designed to describe what I’m doing for people not necessarily familiar with programming or SIMD.) What is SIMD? SIMD stands for “Single Instruction, Multiple Data”, and refers to functionality that a lot of computer hardware has for…
I just pushed travis-cargo version 0.1.3, which adds a --no-sudo command to the coveralls and coverage subcommands to allow recording/uploading test coverage without needing sudo . This is based 0 on @seanmonstar ’s investigation/ implementation of sudo-less kcov . It works because Travis’s apt addon has whitelisted everything necessary. Unfortunately, it does require these to be installed…
Over the past few weeks I’ve been working on improving my slow_primes library, culminating in needing rename and the 0.2 release of primal , a Rust crate for computing properties of prime numbers with state-of-the-art algorithms , while still maintaining an idiomatic and easy-to-use interface. primal My computer takes a quarter of a second and less than 3MB of RAM to tell me that there 50,847,534…
Rust has some powerful tricks to model properties of aggregate types via unsafe traits with default and negative implementations. These features motivated by offering flexible concurrency/parallelism, and allow powerful closure-based APIs without losing any thread-safety (or memory-safety) guarantees at all. I realised that my recent post on the low-level details of closures missed an important…
Rust 1.0 was made with 0 … 1 stable release 2 ‘Rust’ compilers 3 bots on Github 4 years of bootstrapping ( 7b95b5c is the innocuous commit of the first snapshot) 5 years of git ~9 years total 12 0.x releases ~28 launch meetups ~53 irc channels starting with #rust on irc.mozilla.org 80 TWiRs 156 people with project-flair on /r/rust ~174 RFCs 302 comments on the most-commented pull request, #12081…
Have you ever used an iterator adapter in Rust ? Called a method on Option ? Spawned a thread? You’ve almost certainly used a closure . The design in Rust may seem a little complicated, but it slides right into Rust’s normal ownership model so let’s reinvent it from scratch. The new design was introduced in RFC 114 , moving Rust to a model for closures similar to C++11’s. The design builds on…
The concept of object safety in Rust was recently refined to be more flexible in an important way: the checks can be disabled for specific methods by using where clauses to restrict them to only work when Self: Sized . This post is a rather belated fourth entry in my series on trait objects and object safety: Peeking inside Trait Objects , The Sized Trait and Object Safety . It’s been long enough…
After announcing travis-cargo a few days ago in Helping Travis catch the rustc train , I got some great hints/contributions from Jan Segre and had a fun little time automating code coverage collection via coveralls.io . Unfortunately, this is a breaking change for existing users of travis-cargo, but the migration is easy. (If you’re wondering what travis-cargo is, see the linked post .) Version…
I’ve been putting off configuring my continuous integration settings to match the Rust train model: it involves non-trivial branching on the configuration, and duplicating that over a pile of repos is not something I looked forward to. So, instead, I wrote travis-cargo to make things easier. Branching on configuration? One approach to developing Rust libraries once 1.0 is released will be to test…
I’ve been having a lot of fun recently solving “little” problems in Rust. I have a long term project to make something for displaying my (GPS-tagged) photos nicely and, along the way, I’ve discovered and filled in a few gaps by creating focused crates for small tasks. My travels over the last few years, as displayed by the current web interface (served to the browser via Rust, of course). Once an…
Rust is a reasonably large project: the compiler and standard libraries are over 350kloc, built across nearly 40000 commits by the hands of around 900 contributors. Not only that: there are more than 30 other repositories in the rust-lang GitHub organisation that shouldn’t fall by the wayside, and, for rust-lang/rust alone, there are often more than 100 pull requests landing and a dozen new…
If you’ve been in the #rust-internals IRC channel recently, you may’ve caught a madman raving about how much they like Rust: 1 2 3 4 5 ... [15:50:03] <huon> I love this language ... [20:02:07] <huon> did you know: Rust is awesome. ... I was (and still am) losing my mind over how well Sync and Send interact with everything, especially now that the implementation for RFC 458 has landed. I’m aiming…
Rust Sydney had its first event last Monday! The first Rust gathering I know of in Sydney, in Australia, or in the whole southern hemisphere. I had fun meeting all sorts of people interested in Rust: some who’d dived in deep already, some who’d only recently started playing with it, and some who’d been following for a while but had unfortunately not got time to actually use it (hopefully soon!).…
A trait object in Rust 0 can only be constructed out of traits that satisfy certain restrictions, which are collectively called “object safety”. This object safety can appear to be a needless restriction at first, I’ll try to give a deeper understanding into why it exists and related compiler behaviour. This is the second (and a half) in a short series of articles on trait objects. The first one—…
An important piece in my story about trait objects in Rust 0 is the Sized trait , so I’m slotting in this short post between my discussion of low-level details and the post on “object safety” . Other posts in this series on trait objects Peeking inside Trait Objects The Sized Trait Object Safety Where Self Meets Sized: Revisting Object Safety Sized is a (very) special compiler built-in trait that…
One of the most powerful parts of the Rust programming language 0 is the trait system . They form the basis of the generic system and polymorphic functions and types. There’s an interesting use of traits, as so-called “trait objects”, that allows for dynamic polymorphism and heterogeneous uses of types, which I’m going to look at in more detail over a short series of posts. Update 2015-02-19 : A…
Rust is a systems programming language that comes with an awesome package manager Cargo , which hooks into the crates.io registry as one of its possible sources of packages. The packages can have dependency relationships between each other, making the database into a natural directed graph. Rust as we have it today is still relatively new, Cargo is even newer, and crates.io is newer still, so the…
Rust is an in-development 0 systems programming language with a strong focus on no-overhead memory safety. This is achieved through a powerful type system (with similarities to Haskell), and careful tracking of ownership and pointers, guaranteeing safety. However, this is too restrictive for a low-level systems language, an escape hatch is occasionally required. Enter the unsafe keyword. Poking…
After posting a Rust translation of some k -nearest neighbour code , I got a few comments asking “how would you handle errors if you wanted to?”. This is the perfect chance to briefly demonstrate a few idioms. See my previous post for context and the original code; like with the code in that post, this code compiles with rustc 0.11.0-pre-nightly (e55f64f 2014-06-09 01:11:58 -0700) What type of…
In my voyages around the internet, I came across a pair of blog posts which compare the implementation of a k -nearest neighbour ( k -NN) classifier in F# and OCaml. I couldn’t resist writing the code into Rust to see how it fared. Rust is a memory-safe systems language under heavy development; this code compiles with the latest nightly (as of 2014-06-10 12:00 UTC), specifically rustc…