1

我有一个宏,它只生成一个结构的实例,如下所示:

macro_rules! foo {
    () => {{
        let baz_val = baz();
        
        let bar_val = match bar() {
            Ok(val) => val,
            Err(err) => {
                return Err(err);
            }
        };
        
        Ok(Foo(baz_val, bar_val))
    }};
}

如您所见,我根据bar()函数的结果在宏中提前返回。然而,这被解决为一个错误,说:

   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
  --> src/main.rs:23:24
   |
23 |                 return Err(err);
   |                        ^^^^^^^^ expected `()`, found enum `Result`
...
32 |     let foo_val = foo!();
   |                   ------ in this macro invocation
   |
   = note: expected unit type `()`
                   found enum `Result<_, String>`
   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0308`.

这也是具有完整最小可重复样本的操场的永久链接。

我认为这里的问题是类型推断。我想返回示例FooResult中的一个实例,但宏无法推断它。

那么,如何在声明性宏中提前返回并推断/定义返回类型?


环境

  • 锈病 1.55.0
4

2 回答 2

1

@Netwave 的答案的替代方法是使用仅夜间功能label-break-value

#![feature(label_break_value)]

macro_rules! foo {
    () => {'foo: {
        let baz_val = baz();

        let bar_val = match bar() {
            Ok(val) => val,
            Err(err) => {
                break 'foo Err(err);
            }
        };

        Ok(Foo(baz_val, bar_val))
    }};
}

操场

我相信此功能被明确设计为能够从任意块“返回”,这几乎是您的情况。

于 2021-10-10T18:13:52.777 回答
1

return用于不在宏中的函数中。对于预期的行为,您可以将宏包装到闭包中并立即调用它:

macro_rules! foo {
    () => {{
        (|| {
        let baz_val = baz();

        let bar_val = match bar() {
            Ok(val) => val,
            Err(err) => {
                return Err(err);
            }
        };

        Ok(Foo(baz_val, bar_val))
        })()

    }};
}

操场

于 2021-10-10T13:35:48.917 回答