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

时间:2016-07-20 16:13:15

标签: rust

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

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() {}

结果是:

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>)

如果enum的$ fname共享相同的循环,那么它的$ fname是否应与$ fname相同?

Play it.

2 个答案:

答案 0 :(得分:2)

宏扩展为:

p

<?php /** * Template Name: Home Page * The template for displaying all of today's posts on home page. * * This is the template that displays only today's posts. * Please note that this is the WordPress construct of pages and that * other "pages" on your WordPress site will use a different template. * * @package WordPress * @subpackage Twenty_Fifteen * @since Twenty Fifteen 1.0 */ get_header(); ?> <?php $today = getdate(); $args = array( 'date_query' => array( array( 'year' => $today['year'], 'month' => $today['mon'], 'day' => $today['mday'], ), ), ); $query = new WP_Query( $args ); ?> <div id="primary" class="content-area"> <main id="main" class="site-main" role="main"> <?php // Start the loop. if ($query->have_posts() ) echo'<ul>'; while ( $query->have_posts() ) { $query->the_post(); } echo '</ul>'; // Include the page content template. get_template_part( 'content', 'page' ); // If comments are open or we have at least one comment, load up the comment template. if ( comments_open() || get_comments_number() ) : comments_template(); /* Restore Post Data */ wp_reset_postdata(); else : // no posts found. ; endif ; ?> </main><!-- .site-main --> </div><!-- .content-area --> <?php get_footer(); ?> 的类型是什么?根据运行时的某些内容,编译时类型必须不同;这在像Rust这样的静态类型语言中没有意义。

我建议调查std::any,这看起来与您可能尝试的类似。

答案 1 :(得分:0)

作为替代方案,您可能希望使用Box<Any>进行运行时转换:

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