首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rust宏中参数重复的奇怪行为

Rust宏中参数重复的奇怪行为
EN

Stack Overflow用户
提问于 2016-07-21 00:13:15
回答 2查看 63关注 0票数 0

在Rust中创建宏时遇到重复参数不匹配的奇怪情况:

代码语言:javascript
复制
use std::mem;

trait Object {}

#[derive(Debug)]
struct This {}
impl Object for This {}

#[derive(Debug)]
struct That {}
impl Object for That {}

macro_rules! types {
    ($($fname:ident),*) => {
        enum Type {
            $($fname),*
        }

        fn match_it(t: Type, b: Box<Object>) {
            let p = match t {
                $(
                Type::$fname => {
                    mem::transmute::<Box<Object>, Box<$fname>>(b)
                }
                ),*
            };
        }
    }
}

types!(This, That);

fn main() {}

其结果是:

代码语言:javascript
复制
error: match arms have incompatible types [--explain E0308]
  --> <anon>:20:21
20 |>             let p = match t {
   |>                     ^ expected struct `This`, found struct `That`
<anon>:31:1: 31:20: note: in this expansion of types! (defined in <anon>)
note: expected type `Box<This>`
note:    found type `Box<That>`
note: match arm with an incompatible type
  --> <anon>:22:33
22 |>                 Type::$fname => {
   |>                                 ^
<anon>:31:1: 31:20: note: in this expansion of types! (defined in <anon>)

如果枚举的$fname和Box的$fname共享相同的循环,那么它们不应该是相同的吗?

Play it.

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-07-21 00:25:52

宏将展开为类似以下内容:

代码语言:javascript
复制
enum Type {This, That }

fn match_it(t: Type, b: Box<Object>) {
    let p = match t {
        Type::This => mem::transmute::<Box<Object>, Box<This>>(b),
        Type::That => mem::transmute::<Box<Object>, Box<That>>(b),
    }
}

p的类型是什么?根据运行时的不同,编译时类型必须不同;这在像Rust这样的静态类型语言中没有意义。

我建议研究一下std::any,这似乎与您可能正在尝试做的事情相似。

票数 2
EN

Stack Overflow用户

发布于 2016-07-21 02:58:38

作为另一种选择,也许您希望在运行时使用Box<Any>进行类型转换

代码语言:javascript
复制
use std::any::Any;

struct N(isize);
struct S(String);

fn main() {
    let mut v: Vec<Box<Any>> = Vec::new();

    v.push(Box::new(N(17)));
    v.push(Box::new(S("foo".to_string())));

    let s = v.pop().unwrap().downcast::<S>().unwrap();
    let n = v.pop().unwrap().downcast::<N>().unwrap();
    println!("Extracted {} and {}", s.0, n.0);
}

Play link

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38485681

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档