# Make possible to use procedural macros with scopes

**URL:** <https://internals.rust-lang.org/t/make-possible-to-use-procedural-macros-with-scopes/17778>\
**Category:** language design\
**Created:** [November 20, 2022, 6:41am UTC](https://internals.rust-lang.org/t/make-possible-to-use-procedural-macros-with-scopes/17778 "2022-11-20T06:41:33Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jerrody](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jerrody/32/9983_2.png) [@Jerrody](https://internals.rust-lang.org/u/Jerrody)\
**Post date:** [November 20, 2022, 6:41am UTC](https://internals.rust-lang.org/t/make-possible-to-use-procedural-macros-with-scopes/17778/1 "2022-11-20T06:41:33Z")

</div>

Example usage:

```rust
fn main() {
    let x = {
        #[cfg(debug_assertions)]
        5
        
        #[cfg(not(debug_asserttions))]
        3
    };
    
    println!("{x}");
}

```

or

```rust
        let debug_utils = {
            #[cfg(validation)]
            Some({
                let debug_utils_info = vk::DebugUtilsMessengerCreateInfoEXT::default()
                    .message_severity(
                        vk::DebugUtilsMessageSeverityFlagsEXT::ERROR
                            | vk::DebugUtilsMessageSeverityFlagsEXT::WARNING
                            | vk::DebugUtilsMessageSeverityFlagsEXT::INFO,
                    )
                    .message_type(
                        vk::DebugUtilsMessageTypeFlagsEXT::GENERAL
                            | vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE
                            | vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION,
                    );

                let debug_loader = ash::extensions::ext::DebugUtils::new(&entry, &instance);
                unsafe {
                    debug_loader
                        .create_debug_utils_messenger(&debug_utils_info, None)
                        .unwrap()
                }
            })

            #[cfg(not(validation))]
            None
        };

```

Currently it gives an error:

1. 

```rust
error: expected `;`, found `#`
 --> src/main.rs:4:10
  |
4 | 5
  | ^ help: add `;` here
5 |         
6 | #[cfg(not(debug_asserttions))]
  | - unexpected token

error[E0308]: mismatched types
 --> src/main.rs:4:9
  |
4 | 5
  | ^ expected `()`, found integer

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to 2 previous errors

```

1. 

```rust
error: expected `;`, found `#`
  --> src\engine\backend\mod.rs:77:15
   |
77 | })
   | ^ help: add `;` here
78 |
79 | #[cfg(not(validation))]
   | - unexpected token

error: could not compile `vulkan_learning` due to previous error

```

---

<div class="post-metadata">

**Author:** ![2e71828](https://avatars.discourse-cdn.com/v4/letter/2/3e96dc/32.png) [@2e71828](https://internals.rust-lang.org/u/2e71828)\
**Post date:** [November 20, 2022, 7:21am UTC](https://internals.rust-lang.org/t/make-possible-to-use-procedural-macros-with-scopes/17778/2 "2022-11-20T07:21:55Z")

</div>

Setting aside the potential issues that arise if the various attributes aren’t exhaustive, the problem with annotating expressions instead of statements is that they’re recursive: Many different expressions of different nesting levels start at the same point. For example, what does this evaluate to when `p` is true, 3 or 8?

```rust
#[cfg(p)] 3 #[cfg(not(p))] 4 + 5

```

Your examples can be made to compile today by lifting the annotation to cover the containing `let` statement. The resulting duplication seems like a small price to pay to avoid the ambiguity above; do you have any examples where lifting the annotation to an entire statement is a significant burden?

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [November 20, 2022, 10:01am UTC](https://internals.rust-lang.org/t/make-possible-to-use-procedural-macros-with-scopes/17778/3 "2022-11-20T10:01:37Z")

</div>

You don't even need to lift the cfg to the `let` — you just need to cfg blocks instead of expressions, e.g.

```rust
fn main() {
    let x = {
        #[cfg(debug_assertions)] {
            5
        }
        
        #[cfg(not(debug_asserttions))] {
            3
        }
    };
    
    println!("{x}");
}

```

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [November 20, 2022, 5:18pm UTC](https://internals.rust-lang.org/t/make-possible-to-use-procedural-macros-with-scopes/17778/4 "2022-11-20T17:18:17Z")

</div>

```rust
let x = if cfg!(debug_assertions) { 5 } else { 3 };

```

---

<div class="post-metadata">

**Author:** ![Jerrody](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jerrody/32/9983_2.png) [@Jerrody](https://internals.rust-lang.org/u/Jerrody)\
**Post date:** [November 23, 2022, 6:34pm UTC](https://internals.rust-lang.org/t/make-possible-to-use-procedural-macros-with-scopes/17778/5 "2022-11-23T18:34:56Z")

</div>

This is a runtime check. But I speak about compile-time.

---

<div class="post-metadata">

**Author:** ![sahnehaeubchen](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/sahnehaeubchen/32/9709_2.png) [@sahnehaeubchen](https://internals.rust-lang.org/u/sahnehaeubchen)\
**Post date:** [November 23, 2022, 10:10pm UTC](https://internals.rust-lang.org/t/make-possible-to-use-procedural-macros-with-scopes/17778/6 "2022-11-23T22:10:35Z")

</div>

There is no runtime check. The other branch is completly removed even without optimizations: [Compiler Explorer](https://rust.godbolt.org/z/6G397zcfK)

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [November 23, 2022, 11:01pm UTC](https://internals.rust-lang.org/t/make-possible-to-use-procedural-macros-with-scopes/17778/7 "2022-11-23T23:01:53Z")

</div>

It's trivially removed, yes, but it still needs to typecheck, and thus can't use `#[cfg]`d functionality.

`if cfg!` is typically better if both arms _do_ always compile (not the least because you always check both arms compile), but `#[cfg]` blocks are still sometimes required.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [February 21, 2023, 11:02pm UTC](https://internals.rust-lang.org/t/make-possible-to-use-procedural-macros-with-scopes/17778/8 "2023-02-21T23:02:04Z")

</div>

Closed on February 21, 2023, 11:02pm UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
