Skip to main content

The Turbofish remains undefeated.


// Beware travellers, lest you venture into waters callous and unforgiving,
// where hope must be abandoned, ere it is cruelly torn from you. For here
// stands the bastion of the Turbofish: an impenetrable fortress holding
// unshaking against those who would dare suggest the supererogation of the
// Turbofish.
// Once I was young and foolish and had the impudence to imagine that I could
// shake free from the coils by which that creature had us tightly bound. I
// dared to suggest that there was a better way: a brighter future, in which
// Rustaceans both new and old could be rid of that vile beast. But alas! In
// my foolhardiness my ignorance was unveiled and my dreams were dashed
// unforgivingly against the rock of syntactic ambiguity.
// This humble program, small and insignificant though it might seem,
// demonstrates that to which we had previously cast a blind eye: an ambiguity
// in permitting generic arguments to be provided without the consent of the
// Great Turbofish. Should you be so na簿ve as to try to revolt against its
// mighty clutches, here shall its wrath be indomitably displayed. This
// program must pass for all eternity: forever watched by the guardian angel
// which gave this beast its name, and stands fundamentally at odds with the
// impetuous rebellion against the Turbofish.
// My heart aches in sorrow, for I know I am defeated. Let this be a warning
// to all those who come after: for they too must overcome the impassible
// hurdle of defeating the great beast, championed by a resolute winged
// guardian.
// Here stands the Bastion of the Turbofish, a memorial to Anna Harren,
// Guardian Angel of these Hallowed Grounds. <3

// See
// and
// and
// for context.

fn main() {
let (the, guardian, stands, resolute) = ("the", "Turbofish", "remains", "undefeated");
let _: (bool, bool) = (the<guardian, stands>(resolute));

Still unclear why is this code problematic? This explains the issue better:

fn main() {
let (oh, woe, is, me) = ("oh", "woe", "is", "me");

// at first glance this looks like "oh" is a function
// which is being called with 2 type args: "woe" & "is"
// and being invoked with 1 arg: "me"
// which obvs doesn't make any sense since we know these are all &str
let _ = (oh<woe, is>(me));

// after staring at it for a bit the outer parens aren't superfluous
// but define a tuple, with the comma in the middle separate 2 tuple items.

// the left tuple item is the result of comparing "oh" to "woe" which
// results in a bool, and the same is true for the right tuple item,
// although "me" is wrapped in superfluous parens just to be confusing.

// here's it but more clearly formatted
let _: (bool, bool) = (oh < woe, is > me);


console.log(Math.imul(3, 4));
// expected output: 12

console.log(Math.imul(-5, 12));
// expected output: -60

console.log(Math.imul(0xffffffff, 5));
// expected output: -5

console.log(Math.imul(0xfffffffe, 5));
// expected output: -10

The reason imul exists is because it is faster in only one (so far) circumstance: AsmJS. AsmJS allows for JIT-optimizers to more easily implement internal integers in JavaScript. Multiplying two numbers stored internally as integers (which is only possible with AsmJS) with imul is the only potential circumstance where Math.imul may prove performant in current browsers.

Also: Why would I use Math.imul()?

This happened today. I couldn't start my Rust server because port 5000 was already occupied. But by whom? I did some digging, and I got something like this:

$ lsof -i :5000
ControlCe 1677 user 32u IPv4 0x728ff8e52d51c6dd 0t0 TCP *:commplex-main (LISTEN)
ControlCe 1677 user 33u IPv6 0x728ff8e51d98ec65 0t0 TCP *:commplex-main (LISTEN)

Hmm? I tried to kill the process but that didn't help. It took me a while to research that the culprit is macOS Monterey (I didn't start the server ever since I upgraded to this macOS version):

Solution: Go to System Preference --> Sharing --> uncheck off the "AirPlay Receiver"


Relay version 13 shipped with a new Rust Compiler and requires migration to the new Flow type names. @kassens described the migration path well in this comment:

  • SomeFragment$data (instead of SomeFragment (no suffix))
  • SomeFragment$fragmentType (instead of SomeFragment$ref)
  • SomeQuery$variables (instead of SomeQueryVariables)
  • SomeQuery$data (instead of SomeQueryResponse, as it works like the $data for fragments and isn't the full response)
  • $fragmentSpreads (as a key in generated files instead of $refs)

I also asked about the new Flow types here:

Global constant __DEV__ is not part of the ReScript language, but you can use it via %external. It is a common pattern that allows you to easily distinguish dev and prod environments. I started using it in my projects as well.

switch %external(__DEV__) {
| Some(_) => Js.log("dev mode")
| None => Js.log("production mode")

The code above translates to something like this:

var match$1 = typeof __DEV__ === 'undefined' ? undefined : __DEV__;
if (match$1 !== undefined) {
console.log('dev mode');
} else {
console.log('production mode');

Obviously, this code still needs some kind of transpilation (since __DEV__ doesn't exist in JS either).

Write a function called strictEquals(a, b) that returns the same value as a === b. Your implementation must not use the === or !== operators.


function strictEquals(a, b) {
if (, b)) {
// Same value.
// Is this NaN?
if (, NaN)) {
// We already know a and b are the same, so it's enough to check a.
// Special case #1.
return false;
} else {
// They are equal!
return true;
} else {
// Different value.
// Are these 0 and -0?
if ((, 0) &&, -0)) || (, -0) &&, 0))) {
// Special case #2.
return true;
} else {
// They are not equal!
return false;

/* Present: selects .foo elements with bar attribute present, regardless of its value */
.foo[bar] {
fum: baz;

/* Exact: selects .foo elements where the bar attribute has the exact value of fum */
.foo[bar='fum'] {
baz: qux;

/* Whitespace separated: selects .foo elements with bar attribute values contain specified partial value of fum (whitespace separated) */
.foo[bar~='fum'] {
baz: qux;

/* Hyphen separated: selects .foo elements with bar attribute values contain specified partial value of fum immediately followed by hyphen (-) character */
.foo[bar|='fum'] {
baz: qux;

/* Begins with: selects .foo elements where the bar attribute begins with fum */
.foo[bar^='fum'] {
baz: qux;

/* Ends with: selects .foo elements where the bar attribute ends with fum */
.foo[bar$='fum'] {
baz: qux;

/* Containts: selects .foo elements where the bar attribute contains string fum followed and preceded by any number of other characters */
.foo[bar*='fum'] {
baz: qux;