无法满足 Into<i64> 特征界限
Unable to satisfy Into<i64> trait bound
出于某种原因,我无法通过网络搜索找到任何答案。
所以我有一个使用 libc
板条箱(一个简单的包装器)的类型同义词:
pub type SyscallResult<R: Into<i64>> = Result<R, c_int>;
Into<i64>
的意义在于一些系统调用有 i32
或 i64
结果,但 errno
始终是 i32
。 (c_int
-> i32
)
在函数签名中使用 std
提供的具体类型没有问题。
pub fn handle_syscall_result(result: SyscallResult<i64>) -> i64
{
match result {
Ok(status: i64) => status,
Err(errno: c_int) => {
let err = unsafe { CStr::from_ptr(libc::strerror(errno)) };
println!("{:?}", err);
errno as i64
}
}
}
但是当我尝试将特征绑定传播到函数的签名中时,事情开始变得混乱:
fn new_syscall_result<T>(status: Option<T>) -> SyscallResult<i64>
where
T: Into::<i64>,
{
let errno: c_int = errno();
match errno {
-1 => Err(errno),
_ => Ok(status.unwrap_or(errno)),
}
}
给予
error[E0308]: mismatched types
-->
|
35 | fn new_syscall_result<T>(status: Option<T>) -> SyscallResult<i64>
| - this type parameter
...
43 | _ => Ok(status.unwrap_or(errno)),
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `i64`, found type parameter `T`
|
= note: expected type `i64`
found type parameter `T`
这让它看起来像是在做正确的事情,因为 i32
被转换为 i64
,但由于某种原因它不满足特征界限 T
?
展开 Option<T>
应该自然地给出 T
并且从我从 std::convert::From
文档中读到的内容来看,Into<i64>
应该为 i64
实现为很好(反身性),尽管即使它没有被强制转换 From<i32> for i64
也是一个有效的实现,这意味着 Into<i64> for i32
应该存在。
将 return 类型切换为 SyscallResult<T>
也没有任何区别
error[E0308]: mismatched types
-->
|
35 | fn new_syscall_result<T>(status: Option<T>) -> SyscallResult<T>
| - this type parameter
...
43 | _ => Ok(status.unwrap_or(errno)),
| ^^^^^ expected type parameter `T`, found `i32`
|
= note: expected type parameter `T`
found type `i32`
您需要显式调用 into()
:
_ => Ok(status.map(Into::<i64>::into).unwrap_or(errno.into())),
// ^^^^^^^^^^^^^^^^^^^^^^
status
是一个 Option<T>
,你想要一个 Option<i64>
的机器人。为此,我们使用 Option::map
.
转换 Option
中包含的类型
你的代码还有一个问题:
_ => Ok(status.map(Into::<i64>::into).unwrap_or(errno.into())),
// ^^^^^^^^^^^^
errno
是一个 c_int
,所以在大多数平台上是一个 i32
,但我们需要一个 i64
。同样,必须使用 into()
来转换类型。这里不需要显式类型注释,编译器可以从上下文中推断出正确的类型。或者,您也可以在此处使用强制转换:
_ => Ok(status.map(Into::<i64>::into).unwrap_or(errno as i64)),
出于某种原因,我无法通过网络搜索找到任何答案。
所以我有一个使用 libc
板条箱(一个简单的包装器)的类型同义词:
pub type SyscallResult<R: Into<i64>> = Result<R, c_int>;
Into<i64>
的意义在于一些系统调用有 i32
或 i64
结果,但 errno
始终是 i32
。 (c_int
-> i32
)
在函数签名中使用 std
提供的具体类型没有问题。
pub fn handle_syscall_result(result: SyscallResult<i64>) -> i64
{
match result {
Ok(status: i64) => status,
Err(errno: c_int) => {
let err = unsafe { CStr::from_ptr(libc::strerror(errno)) };
println!("{:?}", err);
errno as i64
}
}
}
但是当我尝试将特征绑定传播到函数的签名中时,事情开始变得混乱:
fn new_syscall_result<T>(status: Option<T>) -> SyscallResult<i64>
where
T: Into::<i64>,
{
let errno: c_int = errno();
match errno {
-1 => Err(errno),
_ => Ok(status.unwrap_or(errno)),
}
}
给予
error[E0308]: mismatched types
-->
|
35 | fn new_syscall_result<T>(status: Option<T>) -> SyscallResult<i64>
| - this type parameter
...
43 | _ => Ok(status.unwrap_or(errno)),
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `i64`, found type parameter `T`
|
= note: expected type `i64`
found type parameter `T`
这让它看起来像是在做正确的事情,因为 i32
被转换为 i64
,但由于某种原因它不满足特征界限 T
?
展开 Option<T>
应该自然地给出 T
并且从我从 std::convert::From
文档中读到的内容来看,Into<i64>
应该为 i64
实现为很好(反身性),尽管即使它没有被强制转换 From<i32> for i64
也是一个有效的实现,这意味着 Into<i64> for i32
应该存在。
将 return 类型切换为 SyscallResult<T>
也没有任何区别
error[E0308]: mismatched types
-->
|
35 | fn new_syscall_result<T>(status: Option<T>) -> SyscallResult<T>
| - this type parameter
...
43 | _ => Ok(status.unwrap_or(errno)),
| ^^^^^ expected type parameter `T`, found `i32`
|
= note: expected type parameter `T`
found type `i32`
您需要显式调用 into()
:
_ => Ok(status.map(Into::<i64>::into).unwrap_or(errno.into())),
// ^^^^^^^^^^^^^^^^^^^^^^
status
是一个 Option<T>
,你想要一个 Option<i64>
的机器人。为此,我们使用 Option::map
.
Option
中包含的类型
你的代码还有一个问题:
_ => Ok(status.map(Into::<i64>::into).unwrap_or(errno.into())),
// ^^^^^^^^^^^^
errno
是一个 c_int
,所以在大多数平台上是一个 i32
,但我们需要一个 i64
。同样,必须使用 into()
来转换类型。这里不需要显式类型注释,编译器可以从上下文中推断出正确的类型。或者,您也可以在此处使用强制转换:
_ => Ok(status.map(Into::<i64>::into).unwrap_or(errno as i64)),