我想在Rust中为大多数Rem
类型实现modulo操作:
#![feature(specialization)]
use std::ops::{Add, Rem};
/// Define a modulo operation, in the mathematical sense.
/// This differs from Rem because the result is always non-negative.
pub trait Modulo<T> {
type Output;
#[inline]
fn modulo(self, other: T) -> Self::Output;
}
/// Implement modulo operation for types that implement Rem, Add and Clone.
// Add and Clone are needed to shift the value by U if it is below zero.
impl<U, T> Modulo<T> for U
where
T: Clone,
U: Rem<T>,
<U as Rem<T>>::Output: Add<T>,
<<U as Rem<T>>::Output as Add<T>>::Output: Rem<T>
{
default type Output = <<<U as Rem<T>>::Output as Add<T>>::Output as Rem<T>>::Output;
#[inline]
default fn modulo(self, other: T) -> Self::Output {
((self % other.clone()) + other.clone()) % other
}
}
在没有default
的情况下可以正常编译,但是在有了default
的情况下,我可以得到
error[E0308]: mismatched types
--> main.rs:
|
| default fn modulo(self, other: T) -> Self::Output {
| ------------ expected `<U as Modulo<T>>::Output` because of return type
| ((self % other.clone()) + other.clone()) % other
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected Modulo::Output, found std::ops::Rem::Output
|
= note: expected type `<U as Modulo<T>>::Output`
found type `<<<U as std::ops::Rem<T>>::Output as std::ops::Add<T>>::Output as std::ops::Rem<T>>::Output`
我不明白为什么会这样。我需要default
,因为我想专门针对Copy
类型。
我每晚使用Rust 1.29.0。
答案 0 :(得分:1)
以下是该问题(MCVE)的较小再现:
#![feature(specialization)]
trait Example {
type Output;
fn foo(&self) -> Self::Output;
}
impl<T> Example for T {
default type Output = i32;
default fn foo(&self) -> Self::Output {
42
}
}
fn main() {}
之所以出现问题,是因为该实现的特殊化可以选择对Output
或foo
进行特殊化,但不必同时进行这两种操作:
impl<T> Example for T
where
T: Copy,
{
type Output = bool;
}
在这种情况下,foo
的原始实现将不再有意义-它不再返回类型为Self::Output
的值。
当前的专业化实现要求您在本地和全局范围内进行思考,这是您必须阅读错误消息的上下文。这不是理想的选择,但存在诸如此类的问题(我相信还有很多更复杂的问题)部分原因是它还不稳定。