๐Ÿฆ€ Functional Rust
๐ŸŽฌ Error Handling in Rust Option, Result, the ? operator, and combinators.
๐Ÿ“ Text version (for readers / accessibility)

โ€ข Option represents a value that may or may not exist โ€” Some(value) or None

โ€ข Result represents success (Ok) or failure (Err) โ€” no exceptions needed

โ€ข The ? operator propagates errors up the call stack concisely

โ€ข Combinators like .map(), .and_then(), .unwrap_or() chain fallible operations

โ€ข The compiler forces you to handle every error case โ€” no silent failures

310: Infallible Conversions

Difficulty: 3 Level: Advanced `std::convert::Infallible` โ€” the error type for conversions that cannot fail, and how `From` and `TryFrom` relate.

The Problem This Solves

Rust's conversion traits split into two families: `From`/`Into` for conversions that always succeed, and `TryFrom`/`TryInto` for conversions that might fail. This is clean in principle, but breaks down when you need to write generic code that works with both. A generic function that accepts `TryFrom<T>` cannot accept `From<T>` implementations without a separate constraint โ€” even though `From` implies infallibility. The solution is `Infallible`. Every `From<T> for U` implementation automatically gives you `TryFrom<T, Error = Infallible> for U` via a blanket impl in the standard library. This unifies both families: `TryFrom` is the general form, `From` is the special case where the error type is `Infallible`. Generic code can now accept `TryFrom<T>` and work for both fallible and infallible conversions. The practical benefit extends to API design. When you're implementing a trait that requires `TryFrom` (because it's part of a generic interface), but your specific type's conversion truly cannot fail, you can implement `From` and get `TryFrom` for free โ€” with `Infallible` as the documented proof that failure is impossible.

The Intuition

`Infallible` is an enum with zero variants. You cannot construct a value of type `Infallible`. So `Result<T, Infallible>` is really just `T` in disguise โ€” the `Err` variant can never exist, and `.unwrap()` can never panic. Think of it as a type-level proof: "I claim this conversion cannot fail, and here's the evidence โ€” an error type with no values."

How It Works in Rust

use std::convert::{Infallible, TryFrom};

// From<u8> for u32 is infallible โ€” u8 always fits in u32
let n: u32 = u32::from(255u8); // never fails

// The blanket impl gives us TryFrom for free:
let r: Result<u32, Infallible> = u32::try_from(255u8);
// r is always Ok โ€” Infallible proves it

// Your own type: From gives you TryFrom automatically
struct Meters(f64);
impl From<f64> for Meters {
 fn from(v: f64) -> Self { Meters(v) }
}
// Now Meters::try_from(1.5f64) works with Error = Infallible

// Generic code works with both:
fn convert<T, U: TryFrom<T, Error = Infallible>>(val: T) -> U {
 U::try_from(val).unwrap() // safe โ€” Infallible proves no panic
}

What This Unlocks

Key Differences

ConceptOCamlRust
Infallible conversion`int_of_char` (total function)`From<T>` / `Into<T>`
Fallible conversion`int_of_string` raises exception`TryFrom<T, Error=E>`
Infallible markerN/A (type system doesn't track)`std::convert::Infallible`
Generic over bothManual dispatch`TryFrom<T, Error=Infallible>`
Zero-variant type`type void = \` (empty variant)`enum Infallible {}`
//! 310. Infallible conversions with Into
//!
//! `Infallible` marks conversions that cannot fail; `From<T>` implies `TryFrom<T, Error=Infallible>`.

use std::convert::{TryFrom, TryInto, Infallible};

/// Custom type that wraps a non-zero u32
#[derive(Debug, Clone, Copy, PartialEq)]
struct NonZeroU32(u32);

#[derive(Debug, PartialEq)]
struct ZeroError;

impl TryFrom<u32> for NonZeroU32 {
    type Error = ZeroError;
    fn try_from(n: u32) -> Result<Self, ZeroError> {
        if n == 0 { Err(ZeroError) } else { Ok(NonZeroU32(n)) }
    }
}

/// Infallible conversion: u8 always fits in u32
/// This is provided automatically via From<u8> for u32
#[allow(dead_code)]
fn demonstrate_from() {
    let small: u8 = 255;
    let big: u32 = u32::from(small); // infallible
    println!("u8 {} -> u32 {}", small, big);

    // TryFrom on u32->u8 is fallible
    let large: u32 = 300;
    let result = u8::try_from(large);
    println!("u32 {} -> u8: {:?}", large, result);
}

/// Newtype with infallible From conversion
#[derive(Debug, PartialEq)]
struct Meters(f64);

impl From<f64> for Meters {
    fn from(v: f64) -> Self { Meters(v) }
}

// From<f64> automatically gives us TryFrom<f64, Error=Infallible>
// We can verify:
fn use_try_from(val: f64) -> Result<Meters, Infallible> {
    Meters::try_from(val)
}

fn main() {
    // Standard library From impls
    let n: u32 = u32::from(42u8); // infallible
    println!("u8 -> u32: {}", n);

    let s: String = String::from("hello"); // infallible
    println!("&str -> String: {}", s);

    // TryFrom fallible
    let ok = NonZeroU32::try_from(5u32);
    let err = NonZeroU32::try_from(0u32);
    println!("TryFrom 5: {:?}", ok);
    println!("TryFrom 0: {:?}", err);

    // Into (reverse of From)
    let m: Meters = 100.0f64.into(); // via From<f64>
    println!("Meters: {:?}", m);

    // use_try_from via TryFrom auto-impl
    let result = use_try_from(42.0);
    println!("Infallible TryFrom: {:?}", result);

    demonstrate_from();
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_nonzero_ok() {
        assert_eq!(NonZeroU32::try_from(5), Ok(NonZeroU32(5)));
    }

    #[test]
    fn test_nonzero_err() {
        assert_eq!(NonZeroU32::try_from(0), Err(ZeroError));
    }

    #[test]
    fn test_from_infallible() {
        let n: u32 = u32::from(100u8);
        assert_eq!(n, 100);
    }

    #[test]
    fn test_meters_from() {
        let m: Meters = Meters::from(5.0);
        assert_eq!(m, Meters(5.0));
    }
}
(* 310. Infallible conversions with Into - OCaml *)
(* OCaml: conversion functions are plain functions *)

let () =
  (* Infallible: i32 always fits in i64 *)
  let x : int = 42 in
  let y : int64 = Int64.of_int x in
  Printf.printf "int -> int64: %Ld\n" y;

  (* Infallible: any char is a valid string *)
  let c = 'A' in
  let s = String.make 1 c in
  Printf.printf "char -> string: %s\n" s;

  (* Fallible: string might not parse to int *)
  let parse_int s = match int_of_string_opt s with
    | Some n -> Ok n | None -> Error ("not a number: " ^ s)
  in
  Printf.printf "Parse '42': %s\n"
    (match parse_int "42" with Ok n -> string_of_int n | Error e -> e);
  Printf.printf "Parse 'abc': %s\n"
    (match parse_int "abc" with Ok n -> string_of_int n | Error e -> e)