Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Turn ? into .unwrap() Behind a Feature

As explained in Method, with the consume-question feature enabled, appending ! to the method allows consuming ?.

We can use this to treat ? as an alias for .unwrap().

Example: when an unwrap feature is enabled, replace ? with .unwrap(). Cargo.toml features:

[dependencies]
hooq = { version = "*", features = ["consume-question"] }

# ..

[features]
unwrap = []

Prepare a flavor in hooq.toml. We restrict hook_targets to only ? so tails/returns are unaffected.

[unwrap]
method = """.unwrap()!"""
hook_targets = ["?"]

main.rs:

use hooq::hooq;

fn failable<T>(val: T) -> Result<T, String> {
    Ok(val)
}

#[cfg_attr(not(feature = "unwrap"), hooq(empty))]
#[cfg_attr(feature = "unwrap", hooq(unwrap))]
fn process(flag: bool) -> Result<(), String> {
    if flag {
        return Err("An error occurred".into());
    }

    let _ = failable(42)?;

    Ok(())
}

#[cfg_attr(not(feature = "unwrap"), hooq(empty))]
#[cfg_attr(feature = "unwrap", hooq(unwrap))]
fn main() -> Result<(), Box<dyn std::error::Error>> {
    process(false)?;

    Ok(())
}

Without the unwrap feature, expansion uses the empty flavor and nothing changes:

#![feature(prelude_import)]
#[macro_use]
extern crate std;
#[prelude_import]
use std::prelude::rust_2024::*;
use hooq::hooq;
fn failable<T>(val: T) -> Result<T, String> {
    Ok(val)
}
fn process(flag: bool) -> Result<(), String> {
    if flag {
        return Err("An error occurred".into());
    }
    let _ = failable(42)?;
    Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
    process(false)?;
    Ok(())
}

With the unwrap feature, expansion replaces with .unwrap():

#![feature(prelude_import)]
#[macro_use]
extern crate std;
#[prelude_import]
use std::prelude::rust_2024::*;
use hooq::hooq;
fn failable<T>(val: T) -> Result<T, String> {
    Ok(val)
}
fn process(flag: bool) -> Result<(), String> {
    if flag {
        return Err("An error occurred".into());
    }
    let _ = failable(42).unwrap();
    Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
    process(false).unwrap();
    Ok(())
}

Highlights:

  • You can replace ? with special behaviors like .unwrap().
  • Feature‑gated #[cfg_attr(..., hooq(...))] lets you vary hooks by build configuration.