{
    "archive_path": "archive/1789250680.361286",
    "base_url": "lwn.net/SubscriberLink/1091015/d9e48318ed242b41",
    "basename": "",
    "bookmarked_date": "2026-09-12 22:04",
    "canonical": {
        "archive_org_path": "https://web.archive.org/web/lwn.net/SubscriberLink/1091015/d9e48318ed242b41",
        "dom_path": "output.html",
        "favicon_path": "favicon.ico",
        "git_path": "git/",
        "google_favicon_path": "https://www.google.com/s2/favicons?domain=lwn.net",
        "headers_path": "headers.json",
        "htmltotext_path": "htmltotext.txt",
        "index_path": "index.html",
        "media_path": "media/",
        "mercury_path": "mercury/content.html",
        "pdf_path": "output.pdf",
        "readability_path": "readability/content.html",
        "screenshot_path": "screenshot.png",
        "singlefile_path": "singlefile.html",
        "warc_path": "warc/",
        "wget_path": "lwn.net/SubscriberLink/1091015/d9e48318ed242b41/index.html"
    },
    "domain": "lwn.net",
    "extension": "",
    "hash": "V9DB352STZRNR6HVFT6W",
    "history": {
        "archive_org": [],
        "dom": [],
        "favicon": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--max-time",
                    "120",
                    "--output",
                    "favicon.ico",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://www.google.com/s2/favicons?domain=lwn.net"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-09-12T22:06:15.671024+00:00",
                "index_texts": null,
                "output": "favicon.ico",
                "pwd": "/data/archive/1789250680.361286",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-12T22:06:15.045196+00:00",
                "status": "succeeded"
            }
        ],
        "git": [],
        "headers": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--head",
                    "--max-time",
                    "120",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://lwn.net/SubscriberLink/1091015/d9e48318ed242b41/"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-09-12T22:06:16.174614+00:00",
                "index_texts": null,
                "output": "headers.json",
                "pwd": "/data/archive/1789250680.361286",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-12T22:06:15.676614+00:00",
                "status": "succeeded"
            }
        ],
        "htmltotext": [],
        "media": [],
        "mercury": [
            {
                "cmd": [
                    "/app/node_modules/@postlight/parser/cli.js",
                    "https://lwn.net/SubscriberLink/1091015/d9e48318ed242b41/"
                ],
                "cmd_version": "1.0.0",
                "end_ts": "2026-09-12T22:06:23.156139+00:00",
                "index_texts": null,
                "output": "mercury",
                "pwd": "/data/archive/1789250680.361286",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-12T22:06:19.573301+00:00",
                "status": "succeeded"
            }
        ],
        "pdf": [],
        "readability": [
            {
                "cmd": [
                    "/app/node_modules/readability-extractor/readability-extractor",
                    "/tmp/tmpsmicbbpq",
                    "https://lwn.net/SubscriberLink/1091015/d9e48318ed242b41/"
                ],
                "cmd_version": "0.0.11",
                "end_ts": "2026-09-12T22:06:19.566147+00:00",
                "index_texts": [
                    "[+] Proceed to the article\n                \n\nA function's return type is supposed to indicate the kind of data that it\nproduces. \nRust's \"never\" type, which is\n\ndenoted by an exclamation mark (\"!\"), is the type the language uses to mark\na function that never returns and other places where a value can never occur. For\na long time, the never type was used internally by the compiler, but was\nconsidered an unstable feature. On\n\nAugust\u00a024, after more than two years of work,\nRust-compiler-contributor \"waffle\" finally managed to stabilize the type. It\ntook so long, in part, because it involved a small breaking\nchange to previous Rust editions, which the compiler maintainers needed to\nensure did not impact much real code.\n\n\n\n(Note: Rust also uses exclamation marks to indicate calls to macros. The way the\nsyntax is constructed, a place where it is valid to use the never type is not a\nvalid place to put a macro invocation and vice versa.)\n\n\nWhy a never type?\n\n\nThere are two reasons that Rust has a never type, one practical and one\nphilosophical. The practical reason is that it allows for more efficient generic\ncode. For example, consider the\n\nFromStr trait in the standard library, which is used for types that\ncan be instantiated from a string:\n\n\n    trait FromStr: Sized {\n        type Err;\n        fn from_str(s: &str) -> Result<Self, Self::Err>;\n    }\n\n\n\nFromStr::from_str() either returns a converted result, or a custom\nerror type. For example, attempting to convert \"foo\" into an integer will return\na \nParseIntError. But some types have an infallible conversion. For\nexample, it is always possible to convert a string into a\n\nByteString. That implementation of FromStr could set\nErr to be the never type. Then the compiler would know that the\nerror branch of the returned Result is never present, and could\noptimize out all of the code that touches it or checks for it.\n\n\n    impl FromStr for ByteString {\n        type Err = !;\n        fn from_str(s: &str) -> Result<Self, !> { ... }\n        // Keeps the same generic interface,\n        // but generates code equivalent to:\n        // fn from_str(s: &str) -> Self { ... }\n    }\n\n\n\nThe philosophical reason involves correct type inference. In Rust, constructs\nsuch as if statements and while loops are expressions; their results can be\nassigned to a variable. The compiler needs a type to infer for the result of an\ninfinite loop, if the programmer writes one. That shouldn't come up often in\nreal code, but it turns out to simplify type inference to be able to treat that\ncase uniformly, rather than adding special rules to handle it.\n\n\n\nIn particular, the never type has a useful property for simplifying code: it\nautomatically coerces to any other type. This sounds strange, but it is\nsafe, since the never type represents the \"result\" of a computation that will\nnever produce a value. So, anywhere that the code claims to have a value of the\nnever type, the compiler knows that it can't possibly reach\nthat code, and therefore it's safe to ignore it. This is a form of\ntype-system-driven dead-code elimination.\n\n\n\n\n\nFor both of these reasons, Rust programmers have wanted to be able to use the\nnever type in stable versions of the language. Making that happen\nrequired resolving a particularly thorny corner case.\n\n\nNever fallback\n\n\nBecause of the way that conversions from the never type to other types are\nimplemented, the compiler can sometimes end up in a situation where it cannot\nnaively infer the concrete type of an expression. Consider this example, which\ndefines an anonymous function (using ||, which is like\nPython or LISP's lambda) that never returns, and then calls it in a way\nthat expects a concrete error type (using the\n\n? operator):\n\n\n    let function_that_never_returns = || { loop {} };\n    function_that_never_returns()?;\n\n\n\nThat infinite loop is given a type of ! which is then implicitly\nconverted to whatever the function is supposed to return. But since the function\nis defined locally and not given an explicit type, the compiler does not have\nsufficient information to say what that type is.\nThe problem could be fixed by giving the function an explicit return type:\n\n\n    let function_that_never_returns = || -> Foo { loop {} };\n\n\n\nSince such an annotation would only be required in cases where the function\ncannot return anything, however, it would\nbe a bit pointless to require the programmer to assign a fictitious type to it.\nSo, the compiler includes a special rule: if, after all other type inference has\nbeen done, there is still an ambiguous type that cannot be determined, just assume\nthat it should be the designated fallback type. Prior to the 2024\n\nedition of Rust, that fallback type was () (the unit type, which has\nexactly one possible value). In the 2024 edition, the fallback type was changed\nto ! itself, essentially canceling out the implicit conversion. In the\ncompiler internals, the never type still gets converted to an unknown type and\nthen falls back, but from the programmer's perspective the behavior is identical\nto having the never type only undergo implicit conversion when required for the\ntypes to make sense.\n\n\n\nThat change of behavior was, technically, a breaking change. Type inference for\nsome code could change, which could in turn cause compilation errors. That is\nthe purpose of Rust's edition system: allow breaking changes in the front-end\ndesign of the language without breaking older code or requiring the whole\necosystem to update at once. In this case, however, there were reasons to want\nthe new behavior backported to old editions.\n\n\nNever infallible\n\n\nFor many years, the standard library has had an\n\nInfallible type to work\naround the unstable nature of the never type. It served the same semantic\npurpose as the never type, but did not have any special compiler support.\nTherefore, code using it would be technically correct but suboptimal (such as\nhaving an extra layer of tags in an enumeration or emitting dead code), because\nthe optimizer would not always be able to remove references to\nInfallible. It was planned that, when the never type was\neventually stabilized, Infallible would become a type alias for\n! and all that old code would silently become more efficient. However,\npeople pointed out a handful of ways that redefining\nInfallible had accidentally been made into a breaking change. Since\n! has implicit conversions, changing the definition of\nInfallible could result in existing code needing additional type\nspecifiers in order to type check.\n\n\n\nLuckily, changing the definition of Infallible and changing the default\nfallback type, while both breaking changes, nearly cancel out. Any code that refers to the\nstandard library's Infallible type by name would continue to work; it\nis only places where type inference is implicitly expected to produce\nInfallible that pose a risk of breaking existing code. With Rust's lack\nof implicit conversions in most cases, that will most often come up in places\nwhere the never type used to be implicitly converted to Infallible. If\nInfallible is made to be a type alias of the never type, then those\nplaces may experience never-type fallback, which would, in turn, change the\ninferred type and cause a compilation error if the never fallback type were not\nupdated at the same time.\n\n\n\nWith both changes occurring simultaneously, the Rust maintainers believed that\nalmost all existing Rust code would continue to compile \u2014 but \"almost all\" is\nnot a reassuring qualifier when dealing with backward-incompatible\nchanges. The Rust community does have a solution to this in the form of\n\ncrater, which can download and compile all publicly available Rust\nlibraries from\n\ncrates.io in search of code that is broken by a compiler change.\n\n\nNever say never\n\n\nWaffle ran crater in April and\n\nfound that, while there were 3,300 crates negatively impacted by the change,\nonly seven were fully broken, with the rest broken by depending on old\nversions of libraries that had since been fixed. In the latter case, the problem\nwould theoretically be fixable by releasing backported fixes for a handful of\ncore libraries.\nThis is not an accident; Rust has been emitting a warning whenever\ncode triggers never-type fallback in a way that will break with the new change\nsince 2024, so most libraries had plenty of time to update of their own\ninitiative. The most common remaining error observed by crater is code\nthat calls a generic function without enough type information for the compiler\nto pick a specific return type. Consider this function:\n\n\n    fn foo<T: Default>() -> Result<T, Error> { ... }\n\n\n\nIt returns either a value of some caller-chosen type T that must\nimplement the Default trait, or an error. If\nit is called without specifying a value for T, however, then type\nfallback can kick in:\n\n\n    // No type specified.\n    foo()?;\n\n\n\nPreviously, this would have made the compiler assume that T should be\n(), which implements Default, and so the code compiles. After\nthis change (and on the 2024 edition), the compiler assumes that T\nshould be !, which doesn't implement Default, and therefore\ncauses a compilation error. The fix is to explicitly specify the type that\nfoo() should return, either in the call or by pattern-matching\nassignment.\n\n\n    foo::<()>()?;\n    // or\n    () = foo()?;\n\n\n\nEven though it's not a complicated change, the Rust maintainers were not willing\nto break 3,300 crates. Waffle was\n\nasked to work with the maintainers\nof common libraries to backport simple changes like the above (making a new\n\npatch version, which many Rust build environments will pick up automatically),\nin order to\nreduce the number of libraries depending on broken dependencies. Several library\nauthors were\n\nwilling to make the backports, but some refused on the grounds that those\nold versions were past their end of life. Those maintainers pointed out that\nusers could stay on an older version of Rust or update to the maintained version\nof the library. Even so, the successful backports\naddressed 1,553 of the failing crates.\n\n\n\nAfter fixing a\nhandful of related problems to reduce the number of broken crates even\nfurther, the Rust maintainers eventually agreed that\neven though there would still be some broken code it was worth making the change\nto simplify the language. So, starting in Rust\u00a01.99, the never type will be\nstable and Infallible will be a type alias for the never type. Users\nwho find that this breaks their code have a few options:\n\n\n\nStay on Rust version\u00a01.98.\nUpdate their dependencies to supported versions that include a fix for the\nproblem.\nAdd a patch to explicitly specify the return types of affected function calls.\n\n\n\nOn the one hand, this is\na breaking change, and people may see code that had remained stable\nand working suddenly fail to compile. That could be seen as a violation of\nRust's commitment\nto backward compatibility. On the other hand, the problem is\nrelatively rare, there are multiple simple ways to fix it, it has been warned\nabout for years, and it has always been part of the plan for the language.\nAdditionally, the\nRust maintainers worked directly with the community to find and\naddress the breakage, even going so far as to help backport fixes to long-dead\nversions of popular libraries. So, the whole process could also be seen as an\naffirmation of Rust's commitment to backward compatibility.\n\nIn the\nfuture, people learning the language will hopefully find the never type just a\nlittle less special.\nEither way, most users of Rust will probably not be affected at all, but never\nsay \"never\".\n\n               \n               \nDid you like this article?? Subscribe now at the special discounted rate to get a lot more like it."
                ],
                "output": "readability",
                "pwd": "/data/archive/1789250680.361286",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-12T22:06:17.676809+00:00",
                "status": "succeeded"
            }
        ],
        "screenshot": [],
        "singlefile": [],
        "title": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--max-time",
                    "120",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://lwn.net/SubscriberLink/1091015/d9e48318ed242b41/"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-09-12T22:06:17.672275+00:00",
                "index_texts": null,
                "output": "Stabilizing Rust's never type [LWN.net]",
                "pwd": "/data/archive/1789250680.361286",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-12T22:06:17.647301+00:00",
                "status": "succeeded"
            }
        ],
        "wget": [
            {
                "cmd": [
                    "wget",
                    "--no-verbose",
                    "--adjust-extension",
                    "--convert-links",
                    "--force-directories",
                    "--backup-converted",
                    "--span-hosts",
                    "--no-parent",
                    "-e",
                    "robots=off",
                    "--timeout=120",
                    "--restrict-file-names=windows",
                    "--warc-file=/data/archive/1789250680.361286/warc/1789250776",
                    "--page-requisites",
                    "--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) wget/GNU Wget 1.21.3",
                    "--compression=auto",
                    "https://lwn.net/SubscriberLink/1091015/d9e48318ed242b41/"
                ],
                "cmd_version": "GNU Wget 1.21.3",
                "end_ts": "2026-09-12T22:06:17.641205+00:00",
                "index_texts": null,
                "output": "lwn.net/SubscriberLink/1091015/d9e48318ed242b41/index.html",
                "pwd": "/data/archive/1789250680.361286",
                "schema": "ArchiveResult",
                "start_ts": "2026-09-12T22:06:16.187178+00:00",
                "status": "succeeded"
            }
        ]
    },
    "icons": null,
    "is_archived": true,
    "is_static": false,
    "latest": {
        "archive_org": null,
        "dom": null,
        "favicon": "favicon.ico",
        "git": null,
        "media": null,
        "pdf": null,
        "screenshot": null,
        "singlefile": null,
        "title": "Stabilizing Rust's never type [LWN.net]",
        "warc": null,
        "wget": "lwn.net/SubscriberLink/1091015/d9e48318ed242b41/index.html"
    },
    "link_dir": "/data/archive/1789250680.361286",
    "newest_archive_date": "2026-09-12T22:06:19.573301+00:00",
    "num_failures": 0,
    "num_outputs": 6,
    "oldest_archive_date": "2026-09-12T22:06:15.045196+00:00",
    "path": "/SubscriberLink/1091015/d9e48318ed242b41/",
    "schema": "Link",
    "scheme": "https",
    "snapshot_id": "2a3abe18-9ec2-475a-b379-44f18cb571bf",
    "sources": [
        "/data/sources/1789250680-import.txt"
    ],
    "tags": null,
    "tags_str": "",
    "timestamp": "1789250680.361286",
    "title": "Stabilizing Rust's never type [LWN.net]",
    "updated": "2026-09-12T22:06:15.044813+00:00",
    "updated_date": "2026-09-12 22:06",
    "url": "https://lwn.net/SubscriberLink/1091015/d9e48318ed242b41/"
}