我有一个实现通用特征的非泛型结构.当我在struct上调用一个函数时,我收到以下错误:
error[E0282]: unable to infer enough type information about `_`
--> src/main.rs:35:18
|
35 | cpu.debugger.attach();
| ^^^^^^ cannot infer type for `_`
|
= note: type annotations or generic parameter binding required
Run Code Online (Sandbox Code Playgroud)
我已经尝试添加类型注释和泛型参数绑定,但我显然做错了什么; 我仍然无法编译.我在其他地方有一个类似的代码,它有一个通用的结构,可能是因为struct和trait impl共享的泛型边界允许编译器推断要调用的实际方法实现.
说明问题的最佳方法是使用简化示例:
struct Cpu<M: Memory, D: Debugger<M>> {
mem: M,
debugger: D,
}
impl<M: Memory, D: Debugger<M>> Cpu<M, D> {
fn new(mem: M, debugger: D) -> Self {
Cpu {
mem: mem,
debugger: debugger,
}
}
}
trait Memory {}
struct SimpleMemory;
impl Memory for SimpleMemory {}
trait Debugger<M: Memory> {
fn attach(&mut self) {}
fn step(mem: &M) {}
}
struct NoOpDebugger;
impl<M: Memory> Debugger<M> for NoOpDebugger {}
fn main() {
let mut cpu = Cpu::new(SimpleMemory, NoOpDebugger);
cpu.debugger.attach(); // <-- cannot infer type for `_`
}
Run Code Online (Sandbox Code Playgroud)
请原谅可怜的头衔,但这是我知道如何描述问题的最佳方式.
你有几个选择.
您可以指定要调用attach
方法的特定特征.
fn main() {
let mut cpu = Cpu::new(SimpleMemory, NoOpDebugger);
Debugger::<SimpleMemory>::attach(&mut cpu.debugger);
}
Run Code Online (Sandbox Code Playgroud)
要么
fn main() {
let mut cpu = Cpu::new(SimpleMemory, NoOpDebugger);
<NoOpDebugger as Debugger<SimpleMemory>>::attach(&mut cpu.debugger);
}
Run Code Online (Sandbox Code Playgroud)您可以将attach
方法移动到非通用的supertrait.
trait DebuggerBase {
fn attach(&mut self) {}
}
trait Debugger<M: Memory>: DebuggerBase {
fn step(mem: &M) {}
}
impl DebuggerBase for NoOpDebugger {}
impl<M: Memory> Debugger<M> for NoOpDebugger {}
Run Code Online (Sandbox Code Playgroud)您可以添加PhantomData
成员NoOpDebugger
并使其NoOpDebugger
自身具有通用性,以便每个成员NoOpDebugger<M>
只实现Debugger<M>
相同的成员M
.在您的示例中,M
for NoOpDebugger
将从调用推断出来Cpu::new
.
use std::marker::PhantomData;
struct NoOpDebugger<M>(PhantomData<M>);
impl<M: Memory> Debugger<M> for NoOpDebugger<M> {}
fn main() {
let mut cpu = Cpu::new(SimpleMemory, NoOpDebugger(PhantomData));
cpu.debugger.attach();
}
Run Code Online (Sandbox Code Playgroud)如果实现Debugger
不依赖于M
,并且如果不使用Debugger
作为特征对象,则可以将type参数移动到需要它的方法,并在不需要它的方法上省略它.
trait Debugger {
fn attach(&mut self) {}
fn step<M: Memory>(mem: &M) {}
}
Run Code Online (Sandbox Code Playgroud)