cov*_*sh2 7 traits rust associated-types
我有这个来源:
pub fn draw<G, C>(&self, font: &mut C, draw_state: &DrawState, transform: Matrix2d, g: &mut G)
where
C: CharacterCache,
G: Graphics<Texture = <C as CharacterCache>::Texture>,
{
self.properties.draw(
self.text.as_str(),
&mut font,
&draw_state,
transform,
g,
);
}
Run Code Online (Sandbox Code Playgroud)
而错误
the trait bound `&mut C: graphics::character::CharacterCache` is not satisfied
(the trait `graphics::character::CharacterCache` is not implemented for `&mut C`)
Run Code Online (Sandbox Code Playgroud)
C定义的唯一方面是它实现CharacterCache,但错误说明相反.
DrawState,Matrix2d,CharacterCache和其实施方式中,Texture和self.properties( Text)由活塞2D图形库提供.总的来说,一定有关于特征的东西我误解了.
该Text::draw函数签名:
fn draw<C, G>(
&self,
text: &str,
cache: &mut C,
draw_state: &DrawState,
transform: Matrix2d,
g: &mut G,
) where
C: CharacterCache,
G: Graphics<Texture = C::Texture>,
Run Code Online (Sandbox Code Playgroud)
T,&T和&mut T,都是不同的类型; 这意味着它&mut &mut T同样是一种不同的类型.对于类型的引用,不会自动实现特征.如果您希望为任一引用实现特征,则需要明确地将其写出来.
例如,这表现出同样的问题:
trait Foo {}
#[derive(Debug, Copy, Clone)]
struct S;
impl Foo for S {}
fn example<T>(_: T)
where
T: Foo,
{}
fn main() {
let mut s = S;
example(s);
example(&s); // the trait bound `&S: Foo` is not satisfied
example(&mut s); // the trait bound `&mut S: Foo` is not satisfied
}
Run Code Online (Sandbox Code Playgroud)
引用的特征的显式实现解决了这个问题:
impl<'a> Foo for &'a S {}
impl<'a> Foo for &'a mut S {}
Run Code Online (Sandbox Code Playgroud)
在许多情况下,您可以将函数实现委托给非参考实现.
如果这应该始终为true,则可以通过将其应用于对实现特征的类型的所有引用来实现:
impl<'a, T> Foo for &'a T where T: Foo {}
impl<'a, T> Foo for &'a mut T where T: Foo {}
Run Code Online (Sandbox Code Playgroud)
如果您无法控制特征,则可能需要指定引用实现特征的泛型类型:
fn example<T>(_: &mut T)
where
for<'a> &'a mut T: Foo,
{}
Run Code Online (Sandbox Code Playgroud)
也可以看看:
错误消息显示“graphics::character::CharacterCache未实现&mut C”;事实上,您在where- 子句中所说的只是C: CharacterCache,而不是 &mut C: CharacterCache。
(一般来说,&mut Type: Trait如果只知道的话,就不能得出结论Type: Trait)
我假设.draw您调用的方法self.properties: Text需要 a&mut C作为其参数,因此您可能可以传入fontor &mut *font,但我猜测您额外的间接 via 级别&mut font会导致出现问题。
换句话说:
self.properties.draw(
self.text.as_str(),
&mut font,
// ~~~~~~~~~ is not the same as `font` or `&mut *font`
&draw_state,
transform,
g,
);
Run Code Online (Sandbox Code Playgroud)
这种编码“错误”(引入额外的间接级别)实际上比您在 Rust 中编程时想象的要多。
然而,人们通常不会注意到这一点,因为编译器通常会将预期类型与提供的类型进行比较,并应用所谓的deref 强制转换将给定值转换为适当的参数。
因此,如果您考虑以下代码:
fn gimme_ref_to_i32(x: &i32, amt: i32) -> i32 { *x + amt }
fn gimme_mutref_to_i32(x: &mut i32, amt: i32) { *x += amt; }
let mut concrete = 0;
gimme_mutref_to_i32(&mut concrete, 1);
gimme_mutref_to_i32(&mut &mut concrete, 20);
let i1 = gimme_ref_to_i32(&concrete, 300);
let i2 = gimme_ref_to_i32(& &concrete, 4000);
println!("concrete: {} i1: {} i2: {}", concrete, i1, i2);
Run Code Online (Sandbox Code Playgroud)
它将毫无问题地运行;编译器将自动在借用下面插入取消引用,将其变为&mut &mut concrete、&mut *(&mut concrete)和& &concreteinto & *(&concrete)(在本例中分别称为&mut concrete和&concrete)。
(您可以通过阅读相关的RFC来了解有关 Deref Coercions 历史的更多信息。)
然而,当我们调用的函数需要对类型参数的引用时,这个魔法并不能拯救我们,如下所示:
fn gimme_mutref_to_abs<T: AddAssign>(x: &mut T, amt: T) { *x += amt; }
let mut abstract_ = 0;
gimme_mutref_to_abs(&mut abstract_, 1);
gimme_mutref_to_abs(&mut &mut abstract_, 1);
// ^^^^ ^^^^^^^^^^^^^^
// compiler wants &mut T where T: AddAssign
println!("abstract: {}", abstract_);
Run Code Online (Sandbox Code Playgroud)
在此代码中,Rust 编译器首先假设输入类型 ( ) 将分解为满足 的&mut &mut i32某种类型。&mut TT: AddAssign
它检查第一个可能匹配的情况:剥离第一个&mut,然后查看余数 ( &mut i32) 是否可能是T我们正在搜索的。
&mut i32不实现AddAssign,因此尝试解决特征约束失败。
关键的是:编译器不会决定尝试在此处应用任何强制转换(包括 deref 强制转换);它只是放弃了。我还没有找到关于放弃这里的依据的历史记录,但我从对话(以及编译器的知识)中得到的记忆是特征解析步骤是昂贵的,所以我们选择不尝试搜索潜在的特征强制的每一步。相反,程序员应该找出适当的转换表达式,将给定类型转换为编译器可以T接受的某种中间类型作为预期类型。U
| 归档时间: |
|
| 查看次数: |
2617 次 |
| 最近记录: |