使用命名生命周期参数向下转换类型

问题描述 投票:0回答:1

我有以下代码:

use std::any::Any;
use std::borrow::Cow;

// Base trait for downcasting
pub trait AsTranslationUnit<'a> {
    fn as_any(&self) -> &dyn Any;
}

pub trait TranslationUnit<'a>: AsTranslationUnit<'a> {
    fn file_stem(&self) -> &Cow<'a, str>;
}

// Implementation of AsTranslationUnit for all types implementing TranslationUnit
impl<'a, T: TranslationUnit<'a> + 'a> AsTranslationUnit<'a> for T {
    fn as_any(&self) -> &dyn Any {
        self
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct ModuleInterfaceModel<'a> {
    pub file_stem: Cow<'a, str>,
}

impl<'a> TranslationUnit<'a> for ModuleInterfaceModel<'a> {
    fn file_stem(&self) -> &Cow<'a, str> {
        &self.file_stem
    }
}

fn main() {
    let model = ModuleInterfaceModel {
        file_stem: Cow::Borrowed("example"),
    };

    let tu: &dyn TranslationUnit = &model;

    if let Some(mi) = tu.as_any().downcast_ref::<ModuleInterfaceModel>() {
        println!("Module Interface: {:?}", mi);
    } else {
        println!("Not a Module Interface");
    }
}

这会产生以下错误:

   Compiling playground v0.0.1 (/playground)
error[E0310]: the parameter type `T` may not live long enough
  --> src/main.rs:16:9
   |
16 |         self
   |         ^^^^
   |         |
   |         the parameter type `T` must be valid for the static lifetime...
   |         ...so that the type `T` will meet its required lifetime bounds
   |
help: consider adding an explicit lifetime bound
   |
14 | impl<'a, T: TranslationUnit<'a> + 'a + 'static> AsTranslationUnit<'a> for T {
   |                                      +++++++++

For more information about this error, try `rustc --explain E0310`.
error: could not compile `playground` (bin "playground") due to 1 previous error

我想将任何类型的

TranslationUnit
向下转换为其原始类型,但它们都包含命名生命周期参数,因此我无法成功应用此方法。

在没有

'static
生命周期额外界限(这显然不能解决我的问题)并且不脱离我的结构中的命名生命周期参数的情况下,解决这个问题的更惯用的方法是什么?

rust lifetime downcast
1个回答
0
投票

Any
不支持生命周期。期间。

有一些板条箱支持终身

Any
,例如
transient
,但我不能保证它们的健全性,因为我还没有审查它们。

这是一个使用它的示例:

use std::borrow::Cow;

use transient::{Any, Downcast, Inv, Transient};

// Base trait for downcasting
pub trait AsTranslationUnit<'a> {
    fn as_any(&self) -> &dyn Any<Inv<'a>>;
}

pub trait TranslationUnit<'a>: AsTranslationUnit<'a> + Any<Inv<'a>> {
    fn file_stem(&self) -> &Cow<'a, str>;
}

// Implementation of AsTranslationUnit for all types implementing TranslationUnit
impl<'a, T: TranslationUnit<'a> + 'a> AsTranslationUnit<'a> for T {
    fn as_any(&self) -> &dyn Any<Inv<'a>> {
        self
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Default, Transient)]
pub struct ModuleInterfaceModel<'a> {
    pub file_stem: Cow<'a, str>,
}

impl<'a> TranslationUnit<'a> for ModuleInterfaceModel<'a> {
    fn file_stem(&self) -> &Cow<'a, str> {
        &self.file_stem
    }
}

fn main() {
    let model = ModuleInterfaceModel {
        file_stem: Cow::Borrowed("example"),
    };

    let tu: &dyn TranslationUnit = &model;

    if let Some(mi) = tu.as_any().downcast_ref::<ModuleInterfaceModel>() {
        println!("Module Interface: {:?}", mi);
    } else {
        println!("Not a Module Interface");
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.