Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

make-noop

Crates.io Docs.rs CI License: MIT OR Apache-2.0

Attribute macros that replace function, method, and impl-block bodies with no-ops, and strip a struct down to a unit struct.

The point is to toggle that no-op'ing on a compile-time condition. Pair any of these macros with cfg_attr so that a feature flag (or any cfg) decides whether the real implementation is compiled or quietly replaced with a stub — no #[cfg] blocks duplicating each item, and no runtime branch.

use make_noop::{make_noop, make_unit, noop_returns};

// With the `dry-run` feature on, this becomes a no-op; otherwise it runs for real.
#[cfg_attr(feature = "dry-run", make_noop)]
fn launch_missiles(hardware: &Hardware) {
    hardware.arm();
    hardware.fire();
}

// In `dry-run`, report success without touching the network.
#[cfg_attr(feature = "dry-run", noop_returns(Ok(())))]
fn upload(client: &Client, blob: &[u8]) -> Result<(), Error> {
    client.put(blob)
}

// In `dry-run`, collapse the telemetry buffer to a zero-sized unit struct.
#[cfg_attr(feature = "dry-run", make_unit)]
struct Telemetry {
    events: Vec<Event>,
}

Highlights

  • #[make_noop] applies to a free function, a single method, or an entire impl block (every method becomes a no-op).
  • Value-returning functions return Default::default() by default; override the returned value with #[noop_returns(EXPR)].
  • #[noop_returns(EXPR)] works standalone on a function/method, or on a whole impl block — where it sets a shared return value for every method, except those carrying their own #[noop_returns(OTHER)].
  • #[make_unit] strips a struct's fields, leaving a unit struct.
  • Functions without an explicit return type get an empty body unless they have their own #[noop_returns(EXPR)]. That expression runs and must return ().
  • The original body is discarded — it is not type-checked or executed. Imports or items referenced only from a no-op'd body may therefore become unused.

Installation

cargo add make-noop

Usage

Free functions

use make_noop::{make_noop, noop_returns};

#[make_noop]
fn does_nothing() {
    panic!("skipped");
}

#[make_noop]
fn returns_default() -> Vec<u8> {
    unreachable!() // returns Vec::new()
}

#[noop_returns(String::from("hi"))]
fn greeting() -> String {
    unreachable!() // returns "hi"
}

#[noop_returns(called.set(true))]
fn notify(called: &std::cell::Cell<bool>) {
    unreachable!() // runs the override even without an explicit return type
}

Impl blocks

#[make_noop] on an impl block makes every method a no-op. Individual methods can opt into a custom return value with #[noop_returns(EXPR)]:

use make_noop::{make_noop, noop_returns};

struct Service;

#[make_noop]
impl Service {
    fn code(&self) -> i32 {
        unreachable!() // returns 0 (Default)
    }

    #[noop_returns(String::from("hi"))]
    fn greeting(&self) -> String {
        unreachable!() // returns "hi"
    }
}

#[noop_returns(EXPR)] can also be applied to the impl block itself to set a shared default for methods with explicit return types, still overridable per method. Methods without an explicit return type stay empty unless they have their own override:

use make_noop::noop_returns;

struct Codes;

#[noop_returns(3)]
impl Codes {
    fn first(&self) -> i32 {
        unreachable!() // returns 3
    }

    #[noop_returns(42)]
    fn second(&self) -> i32 {
        unreachable!() // returns 42
    }
}

Unit structs

#[make_unit] discards a struct's fields, leaving a unit struct. It works on structs with named fields and on tuple structs; attributes, visibility, and generics are preserved:

use make_noop::make_unit;

#[make_unit]
#[derive(Debug, Default)]
pub struct Config {
    verbose: bool,
    retries: u32,
}
// Expands to `pub struct Config;` (still `#[derive(Debug, Default)]`)

Notes

  • A function that returns a value must have a return type implementing [Default] unless you supply #[noop_returns(EXPR)].
  • The original body is discarded outright: it is neither type-checked nor executed. Anything referenced only from inside a no-op'd body (for example an import) may consequently be reported as unused.

Minimum supported Rust version

make-noop requires Rust 1.87 or newer. The MSRV is verified in CI and may be raised in a minor version bump.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

Small rust crate to make functions/methods no-op, via macros

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages