不推荐使用的别名不会生成警告

时间:2017-10-26 13:08:07

标签: rust

我有一个库,它曾经为FlatMap实现了顶级公共特征(称之为Option)。现在我已经重构了我的库并将该特征移动到名为option的子模块中,并且通过将FlatMap公开导入到顶级包中来确保向后兼容性。我想提醒用户注意它被弃用的顶级特征。我尝试过以下方法:

pub mod option {
   pub trait FlatMap<T> {}
}
#[deprecated(note="Use option::FlatMap instead")]
pub use option::FlatMap;

但是这不起作用:我现在可以use mylib::FlatMapuse mylib::option::FlatMap并且可以正常工作而不会发出警告。我想第一次使用生成弃用警告。

请注意,我不能使用这样的别名特征:

pub mod option {
   pub trait FlatMap<T> {}
}
#[deprecated(note="Use option::FlatMap instead")]
pub trait FlatMap<T>: option::FlatMap<T> {}
impl<T> FlatMap<T> for Option<T> {}

因为我依赖从Optionoption::FlatMap的隐式转换来向Option实例添加方法,而隐式转换不适用于别名特征。

1 个答案:

答案 0 :(得分:1)

能够在option::FlatMap上调用Option方法不是转换,隐式或其他方式 - 它只是方法的解析方式。如果特征是use d,则可以在对象上解析特征方法,但顶级FlatMap特征没有方法,因此它根本不向对象添加任何内容。

现在看来,在Rust中实现这一目标的最佳方法是将特征(带有所有内容)复制到顶层,注释它#[deprecated],并写一条毯子impl遵循“真实”版本。

pub mod option {
    pub trait FlatMap<T> {
        type Item;
        type FlatMap;
        fn flat_map<F>(self, f: F) -> Self::FlatMap
        where
            F: FnOnce(Self::Item) -> T;
    }
    // ...
}

#[deprecated(note = "Use option::FlatMap instead")]
pub trait FlatMap<T> {
    type Item;
    type FlatMap;
    fn flat_map<F>(self, f: F) -> Self::FlatMap
    where
        F: FnOnce(Self::Item) -> T;
}

#[allow(deprecated)]
impl<T, U> FlatMap<T> for U
where
    U: option::FlatMap<T>,
{
    type Item = U::Item;
    type FlatMap = U::FlatMap;
    fn flat_map<F>(self, f: F) -> Self::FlatMap
    where
        F: FnOnce(Self::Item) -> T,
    {
        option::FlatMap::flat_map(self, f)
    }
}

任何使用“外部”FlatMap的尝试都会生成弃用警告(playground link)。

这种方法的一个限制(除了详细程度)是两个特征不兼容作为特征对象(例如,你无法将&FlatMap传递给期望&option::FlatMap的函数。 )但是,这个特性无论如何都不是对象安全的,所以在这种情况下并不重要。

碰巧,您对flat_map的定义 - 虽然是and_then的概括 - 与several other {{3}的概括不同使用,包括languages。所以你可能想考虑重命名它。 (我认为map_or_default符合名称,与Rust's own Iterator::flat_map上提供的其他方法一致。)