{"id":13822676,"url":"https://github.com/dtolnay/proc-macro-hack","last_synced_at":"2025-12-12T12:14:20.136Z","repository":{"id":55036455,"uuid":"77713689","full_name":"dtolnay/proc-macro-hack","owner":"dtolnay","description":"Procedural macros in expression position","archived":true,"fork":false,"pushed_at":"2022-12-19T18:37:45.000Z","size":348,"stargazers_count":203,"open_issues_count":4,"forks_count":18,"subscribers_count":12,"default_branch":"master","last_synced_at":"2024-05-09T09:38:25.097Z","etag":null,"topics":["hack","proc-macro","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dtolnay.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"dtolnay"}},"created_at":"2016-12-30T22:29:00.000Z","updated_at":"2024-02-24T20:55:45.000Z","dependencies_parsed_at":"2023-01-29T22:31:06.078Z","dependency_job_id":null,"html_url":"https://github.com/dtolnay/proc-macro-hack","commit_stats":null,"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtolnay%2Fproc-macro-hack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtolnay%2Fproc-macro-hack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtolnay%2Fproc-macro-hack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtolnay%2Fproc-macro-hack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dtolnay","download_url":"https://codeload.github.com/dtolnay/proc-macro-hack/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":213893314,"owners_count":15653524,"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","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":["hack","proc-macro","rust"],"created_at":"2024-08-04T08:02:12.261Z","updated_at":"2025-12-12T12:14:14.800Z","avatar_url":"https://github.com/dtolnay.png","language":"Rust","readme":"Procedural macros in expression position\n========================================\n\n[\u003cimg alt=\"github\" src=\"https://img.shields.io/badge/github-dtolnay/proc--macro--hack-8da0cb?style=for-the-badge\u0026labelColor=555555\u0026logo=github\" height=\"20\"\u003e](https://github.com/dtolnay/proc-macro-hack)\n[\u003cimg alt=\"crates.io\" src=\"https://img.shields.io/crates/v/proc-macro-hack.svg?style=for-the-badge\u0026color=fc8d62\u0026logo=rust\" height=\"20\"\u003e](https://crates.io/crates/proc-macro-hack)\n[\u003cimg alt=\"docs.rs\" src=\"https://img.shields.io/badge/docs.rs-proc--macro--hack-66c2a5?style=for-the-badge\u0026labelColor=555555\u0026logo=docs.rs\" height=\"20\"\u003e](https://docs.rs/proc-macro-hack)\n[\u003cimg alt=\"build status\" src=\"https://img.shields.io/github/actions/workflow/status/dtolnay/proc-macro-hack/ci.yml?branch=master\u0026style=for-the-badge\" height=\"20\"\u003e](https://github.com/dtolnay/proc-macro-hack/actions?query=branch%3Amaster)\n\n\u003ctable\u003e\u003ctr\u003e\u003ctd\u003e\u003chr\u003e\n\u003cb\u003eNote:\u003c/b\u003e \u003ci\u003eAs of Rust 1.45 this crate is superseded by native support for\n#[proc_macro] in expression position. Only consider using this crate if you care\nabout supporting compilers between 1.31 and 1.45.\u003c/i\u003e\n\u003chr\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\nSince Rust 1.30, the language supports user-defined function-like procedural\nmacros. However these can only be invoked in item position, not in statements or\nexpressions.\n\nThis crate implements an alternative type of procedural macro that can be\ninvoked in statement or expression position.\n\nThis approach works with any Rust version 1.31+.\n\n## Defining procedural macros\n\nTwo crates are required to define a procedural macro.\n\n### The implementation crate\n\nThis crate must contain nothing but procedural macros. Private helper\nfunctions and private modules are fine but nothing can be public.\n\n[\u0026raquo; example of an implementation crate][demo-hack-impl]\n\nJust like you would use a #\\[proc_macro\\] attribute to define a natively\nsupported procedural macro, use proc-macro-hack's #\\[proc_macro_hack\\]\nattribute to define a procedural macro that works in expression position.\nThe function signature is the same as for ordinary function-like procedural\nmacros.\n\n```rust\nuse proc_macro::TokenStream;\nuse proc_macro_hack::proc_macro_hack;\nuse quote::quote;\nuse syn::{parse_macro_input, Expr};\n\n#[proc_macro_hack]\npub fn add_one(input: TokenStream) -\u003e TokenStream {\n    let expr = parse_macro_input!(input as Expr);\n    TokenStream::from(quote! {\n        1 + (#expr)\n    })\n}\n```\n\n### The declaration crate\n\nThis crate is allowed to contain other public things if you need, for\nexample traits or functions or ordinary macros.\n\n[\u0026raquo; example of a declaration crate][demo-hack]\n\nWithin the declaration crate there needs to be a re-export of your\nprocedural macro from the implementation crate. The re-export also carries a\n\\#\\[proc_macro_hack\\] attribute.\n\n```rust\nuse proc_macro_hack::proc_macro_hack;\n\n/// Add one to an expression.\n///\n/// (Documentation goes here on the re-export, not in the other crate.)\n#[proc_macro_hack]\npub use demo_hack_impl::add_one;\n```\n\nBoth crates depend on `proc-macro-hack`:\n\n```toml\n[dependencies]\nproc-macro-hack = \"0.5\"\n```\n\nAdditionally, your implementation crate (but not your declaration crate) is\na proc macro crate:\n\n```toml\n[lib]\nproc-macro = true\n```\n\n## Using procedural macros\n\nUsers of your crate depend on your declaration crate (not your\nimplementation crate), then use your procedural macros as usual.\n\n[\u0026raquo; example of a downstream crate][example]\n\n```rust\nuse demo_hack::add_one;\n\nfn main() {\n    let two = 2;\n    let nine = add_one!(two) + add_one!(2 + 3);\n    println!(\"nine = {}\", nine);\n}\n```\n\n[demo-hack-impl]: https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack-impl\n[demo-hack]: https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack\n[example]: https://github.com/dtolnay/proc-macro-hack/tree/master/example\n\n## Limitations\n\n- Only proc macros in expression position are supported. Proc macros in pattern\n  position ([#20]) are not supported.\n\n- By default, nested invocations are not supported i.e. the code emitted by a\n  proc-macro-hack macro invocation cannot contain recursive calls to the same\n  proc-macro-hack macro nor calls to any other proc-macro-hack macros. Use\n  [`proc-macro-nested`] if you require support for nested invocations.\n\n- By default, hygiene is structured such that the expanded code can't refer to\n  local variables other than those passed by name somewhere in the macro input.\n  If your macro must refer to *local* variables that don't get named in the\n  macro input, use `#[proc_macro_hack(fake_call_site)]` on the re-export in your\n  declaration crate. *Most macros won't need this.*\n\n- On compilers that are new enough to natively support proc macros in expression\n  position, proc-macro-hack does not automatically use that support, since the\n  hygiene can be subtly different between the two implementations. To opt in to\n  compiling your macro to native `#[proc_macro]` on sufficiently new compilers,\n  use `#[proc_macro_hack(only_hack_old_rustc)]` on the re-export in your\n  declaration crate.\n\n[#10]: https://github.com/dtolnay/proc-macro-hack/issues/10\n[#20]: https://github.com/dtolnay/proc-macro-hack/issues/20\n[`proc-macro-nested`]: https://docs.rs/proc-macro-nested\n\n\u003cbr\u003e\n\n#### License\n\n\u003csup\u003e\nLicensed under either of \u003ca href=\"LICENSE-APACHE\"\u003eApache License, Version\n2.0\u003c/a\u003e or \u003ca href=\"LICENSE-MIT\"\u003eMIT license\u003c/a\u003e at your option.\n\u003c/sup\u003e\n\n\u003cbr\u003e\n\n\u003csub\u003e\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in this hack by you, as defined in the Apache-2.0 license, shall\nbe dual licensed as above, without any additional terms or conditions.\n\u003c/sub\u003e\n","funding_links":["https://github.com/sponsors/dtolnay"],"categories":["Rust"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdtolnay%2Fproc-macro-hack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdtolnay%2Fproc-macro-hack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdtolnay%2Fproc-macro-hack/lists"}