{"id":30450287,"url":"https://github.com/mathiaspius/fallible-option","last_synced_at":"2025-08-23T13:26:45.801Z","repository":{"id":65202824,"uuid":"587338798","full_name":"MathiasPius/fallible-option","owner":"MathiasPius","description":"Fallible is an Option with inverted Try-semantics.","archived":false,"fork":false,"pushed_at":"2023-01-12T14:11:39.000Z","size":27,"stargazers_count":26,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-18T08:29:49.502Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MathiasPius.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2023-01-10T14:22:12.000Z","updated_at":"2024-07-17T20:03:04.000Z","dependencies_parsed_at":"2023-01-13T15:57:53.412Z","dependency_job_id":null,"html_url":"https://github.com/MathiasPius/fallible-option","commit_stats":null,"previous_names":["mathiaspius/errable"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/MathiasPius/fallible-option","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MathiasPius%2Ffallible-option","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MathiasPius%2Ffallible-option/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MathiasPius%2Ffallible-option/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MathiasPius%2Ffallible-option/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MathiasPius","download_url":"https://codeload.github.com/MathiasPius/fallible-option/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MathiasPius%2Ffallible-option/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271749048,"owners_count":24814115,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-23T02:00:09.327Z","response_time":69,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-23T13:26:29.440Z","updated_at":"2025-08-23T13:26:45.792Z","avatar_url":"https://github.com/MathiasPius.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fallible [![Latest Version]][crates.io] [![Docs]][docs.rs]\n\n[Latest Version]: https://img.shields.io/crates/v/fallible-option\n[crates.io]: https://crates.io/crates/fallible-option\n[Docs]: https://docs.rs/fallible-option/badge.svg\n[docs.rs]: https://docs.rs/fallible-option\n\n\u003c!-- cargo-rdme start --\u003e\n\n[`Fallible`](https://docs.rs/fallible-option/latest/fallible_option/enum.Fallible.html) is an [`Option`](https://doc.rust-lang.org/stable/core/option/enum.Option.html) with inverted [`Try`](https://doc.rust-lang.org/stable/core/ops/trait.Try.html#)-semantics.\n\nWhat this means is that using the `?` operator on a `Fallible\u003cE\u003e` will exit early\nif an error `E` is contained within, or instead act as a no-op, if the value is `Success`.\n\nThis is in contrast to `Option` where using `?` on a `None`-value will exit early.\n\n`Fallible` fills the gap left by the [`Result`](https://doc.rust-lang.org/stable/core/result/enum.Result.html) and [`Option`](https://doc.rust-lang.org/stable/core/option/enum.Option.html) types:\n\n|   Potential Success | Potential Failure |\n|---------------------|-------------------|\n|          `Result\u003cT` | `, E\u003e`            |\n|     `Option\u003cT\u003e`     | **`Fallible\u003cE\u003e`**  |\n\n### Example\nThis code illustrates how `Fallible` can be used to write succint\nvalidation code which exits early in case of failure.\n\n```rust\nuse fallible_option::Fallible::{self, Fail, Success};\n\n// Validates the input number `n`, returning a `Fail`\n// if the input number is zero, or `Success` otherwise.\nfn fails_if_number_is_zero(n: u32) -\u003e Fallible\u003c\u0026'static str\u003e {\n    if n == 0 {\n        Fail(\"number is zero\")\n    } else {\n        Success\n    }\n};\n\n// Check many numbers, returning early if a tested\n// number is equal to zero.\nfn check_many_numbers() -\u003e Fallible\u003c\u0026'static str\u003e {\n    fails_if_number_is_zero(1)?;\n    fails_if_number_is_zero(3)?;\n    fails_if_number_is_zero(0)?; // \u003c--- Will cause early exit\n\n    // Following lines are never reached\n    fails_if_number_is_zero(10)?;\n    \n    Success\n}\n\nassert_eq!(check_many_numbers(), Fallible::Fail(\"number is zero\"));\n```\n\n### Motivation\n`Fallible` fills the gap left by `Option` and `Result` and clearly conveys intent and potential outcomes of a function.\n\nA function which returns `Fallible` has only two potential outcomes, it can fail with an error `E`, or it can succeed.\n\n#### Why not `Result`?\nBecause `Result` implies output. Take `std::fs::rename` for instance:\n\nIf I told you that the return type of `rename` was a `Result\u003cT, E\u003e`, what would you guess `T` and `E` to be?\n\nYou might rightly assume that `E` was `std::io::Error`, but what about `T`? It could reasonably return any number of things:\n* The canonical path of the destination of the renamed file.\n* The size of the moved file.\n* The size of the file (if any) replaced by the renamed file.\n* Or perhaps even a handle to the overwritten file.\n\nOf course none of these are true, as the `T` value of `rename` is the unit value `()`. `rename` never\nproduces any output, it can only signal errors. So why not signal that clearly to the user?\n\nI would argue that using a type which signals the potential for failure, but no output upon success would\nmore clearly express the intent and potential outcomes when using this function.\n\n#### Why not `Option`?\nPotential failure *could* be expressed using an `Option\u003cE\u003e`, but as stated above, the `Try`-semantics\nof `Option` makes it unergonomic to work with:\n\n```rust\ntype Error = \u0026'static str;\n\nfn fails_if_number_is_zero(n: u32) -\u003e Option\u003cError\u003e {\n    if n == 0 {\n        Some(\"number is zero\")\n    } else {\n        None\n    }\n};\n\nfn check_many_numbers() -\u003e Option\u003cError\u003e {\n    // We have to explicitly check, since using `?` here would result in an early exit,\n    // if the call returned None, which is the opposite of what we intend.\n    if let Some(err) = fails_if_number_is_zero(1) {\n        return Some(err)\n    }\n\n    // .. Repeating the above three lines for each check is tedious compared to\n    // just using the `?` operator, as in the example.\n\n    None\n}\n```\n\n### Conversion from `Result`\nSwitching from using `Result` to `Fallible` is very simple, as illustrated with this before/after example:\n\n```rust\nfn validate_number(x: u32) -\u003e Result\u003c(), \u0026'static str\u003e {\n    match x {\n        0 ..= 9 =\u003e Err(\"number is too small\"),\n        10..=30 =\u003e Ok(()),\n        31..    =\u003e Err(\"number is too large\")\n    }\n}\n```\nUsing `Fallible`:\n\n```rust\nfn validate_number(x: u32) -\u003e Fallible\u003c\u0026'static str\u003e {\n    match x {\n        0 ..= 9 =\u003e Fail(\"number is too small\"),\n        10..=30 =\u003e Success,\n        31..    =\u003e Fail(\"number is too large\")\n    }\n}\n```\n### Compatibility\n\n`Fallible` contains utility functions for mapping to and from [`Result`] and [`Option`],\nas well as [`FromResidual`] implementations for automatically performing these conversions\nwhen used with the `?` operator.\n```rust\nfn fails_if_true(should_fail: bool) -\u003e Fallible\u003c\u0026'static str\u003e {\n    if should_fail {\n        Fail(\"Darn it!\")\n    } else {\n        Success\n    }\n}\n\nfn try_producing_value() -\u003e Result\u003cu32, \u0026'static str\u003e {\n    fails_if_true(false)?;\n    fails_if_true(true)?;\n\n    Ok(10)\n}\n```\n\n\u003c!-- cargo-rdme end --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathiaspius%2Ffallible-option","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmathiaspius%2Ffallible-option","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathiaspius%2Ffallible-option/lists"}