{"id":28454510,"url":"https://github.com/zesterer/typed_cfg","last_synced_at":"2026-07-09T03:31:07.061Z","repository":{"id":297483029,"uuid":"996918073","full_name":"zesterer/typed_cfg","owner":"zesterer","description":"A type-checked alternative to cfg(feature)","archived":false,"fork":false,"pushed_at":"2025-06-05T17:35:56.000Z","size":4,"stargazers_count":21,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-19T00:52:46.595Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://crates.io/crates/typed_cfg","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zesterer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-05T17:00:08.000Z","updated_at":"2026-03-11T04:53:41.000Z","dependencies_parsed_at":"2025-06-05T18:36:32.404Z","dependency_job_id":"e49c1d44-b4dd-4c6b-8272-bb4f2626e07f","html_url":"https://github.com/zesterer/typed_cfg","commit_stats":null,"previous_names":["zesterer/typed_cfg"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zesterer/typed_cfg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zesterer%2Ftyped_cfg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zesterer%2Ftyped_cfg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zesterer%2Ftyped_cfg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zesterer%2Ftyped_cfg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zesterer","download_url":"https://codeload.github.com/zesterer/typed_cfg/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zesterer%2Ftyped_cfg/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35286002,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-09T02:00:07.329Z","response_time":57,"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-06-06T19:14:33.364Z","updated_at":"2026-07-09T03:31:07.053Z","avatar_url":"https://github.com/zesterer.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `typed_cfg`\n\nA statically-typed and exhaustively-checked alternative to `cfg(feature)`.\n\n## The problem\n\nLet's say you're writing a library. It has two features, `foo` and `bar`.\n\nSome functions are only enabled by `foo`. Some functions are only enabled with `bar`.\n\n```rust\n#[cfg(feature = \"foo\")]\nfn frobnicate() {\n    ...\n}\n\n#[cfg(feature = \"bar\")]\nfn barnicate() {\n    ...\n}\n```\n\nLater in development, you make a mistake. You accidentally call a `bar`-only function from a `foo`-only function. That's\na problem! It means that if a user only wants to enable `foo`, they end up with a *compilation error* unless they enable\n`bar` too - that's a semver-breaking change!\n\n```rust\n#[cfg(feature = \"foo\")]\nfn frobnicate() {\n    ...\n    barnicate(); // Uh oh!\n    ...\n}\n```\n\nHow do you test for this in CI? Most projects do a compilation check with no features enabled and all features enabled,\nbut the only way to catch bugs like this is to do an exhaustive check through *every combination* of features. With just\na handful of features, you already start needing hundreds of compilation checks - clearly, this isn't viable!\n\n## The solution\n\n`typed_cfg` provides a solution: what if Rust's type system could be used to perform these checks?\n\nHere's how it works:\n\n```rust\nuse typed_cfg::*;\n\n// First, we list the features that our crate supports\ncfgs! { feature = { \"foo\", \"bar\" } }\n\n// Next, we express our feature gates as *trait bounds*\n\nfn frobnicate() where feature: Is\u003c\"foo\"\u003e {\n    ...\n}\n\nfn barnicate() where feature: Is\u003c\"bar\"\u003e {\n    ...\n}\n```\n\nThat's it! Users of your crate can call the functions as normal. Only one change is required in CI: we perform a normal\n`cargo check`, but with the `CHECK_CFG` environment variable set.\n\n```\nCHECK_CFG=1 cargo check\n```\n\nNow, let's see what happens if we accidentally make the mistake we made before:\n\n```\nerror[E0277]: Configuration requirements are not always met\n  --\u003e src/main.rs:8:5\n   |\n8  |     barnicate();\n   |     ^^^^^^^^^^^ The compile-time condition cfg(feature = \"bar\") is not always true in this scope\n   |\n   = help: the trait `typed_cfg::Is\u003c\"bar\"\u003e` is not implemented for `feature`\n   = note: Consider adding a `where feature: Is\u003c\"bar\"\u003e` bound to ensure the caller respects the required configuration\nnote: required by a bound in `barnicate`\n  --\u003e src/main.rs:11:31\n   |\n11 | fn barnicate() where feature: Is\u003c\"bar\"\u003e {\n   |                               ^^^^^^^^^ required by this bound in `barnicate`\n```\n\nBingo! The compiler has successfully alerted us to our mistake, and we've avoided breaking our crate's API for\ndownstream users.\n\n## Targets and more\n\n`typed_cfg` doesn't just work with feature flags! Arbitrary cfg keys are also supported, such as `target_family`:\n\n```rust\nuse typed_cfg::*;\n\n// The `read_at` operation is only supported on POSIX-like operating systems!\nfn file_read_at(file: \u0026File, buf: \u0026mut [u8], offset: u64) -\u003e std::io::Result\u003cusize\u003e\n    where target_family: Is\u003c\"unix\"\u003e\n{\n    #[cfg(target_family = \"unix\")]\n    std::os::unix::fs::FileExt::read_at(file, buf, offset)\n\n    // On non-POSIX platforms, the function isn't even callable!\n    #[cfg(not(target_family = \"unix\"))]\n    unreachable!()\n}\n```\n\n## Using `typed_cfg`\n\nUnfortunately, `typed_cfg` does rely on a (currently) nightly-only Rust feature, `trivial_bounds`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzesterer%2Ftyped_cfg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzesterer%2Ftyped_cfg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzesterer%2Ftyped_cfg/lists"}