泛型类型的泛型构造函数的显式类型注释
Explicit type annotation for generic constructor of a generic type
我正在为 C 库编写 Rust 绑定。它实现了一个可以从不同源实体构造的实体,可能在内部保存一些引用。我希望 Rust 类型执行安全的所有权策略,因此包装器结构是通用的,由存储引用的类型参数化。
struct Foobar<T> {
origin: T,
}
然后我为我的 Foobar
类型实现了一些构造函数。
impl<T> Foobar<T> {
fn from_nowhere() -> Foobar<()> {
Foobar { origin: () }
}
fn from_orange<F>(orange: &mut F) -> Foobar<&mut F>
where F: Orange
{
Foobar { origin: orange }
}
fn from_callback<F>(callback: F) -> Foobar<F>
where F: FnMut(u64) -> u64
{
Foobar { origin: callback }
}
}
问题来了:结构体和构造函数都是独立参数化的。虽然可以从其参数推断构造函数类型参数,但构造函数中未使用结构类型参数,因此无法推断。因此,调用构造函数的天真方法
let a = Foobar::from_nowhere();
let b = Foobar::from_orange(&mut fruit);
let c = Foobar::from_callback(|x| x*x);
混淆 rustc:
rustgen.rs:43:13: 43:33 error: unable to infer enough type information about `_`; type annotations required [E0282]
rustgen.rs:43 let a = Foobar::from_nowhere();
可以通过提供一些任意类型的参数来修复它:
let a = Foobar::<()>::from_nowhere();
let b = Foobar::<()>::from_orange(&mut fruit);
let c = Foobar::<()>::from_callback(|x| x*x);
...真是丑陋不堪。解决该问题的另一种方法是将构造函数转换为自由函数,尽管它(有点)不合常理。
问题是,我是不是遗漏了什么?该设计似乎在某种程度上存在缺陷。设计这种类型以仅使用一级泛型的正确方法是什么?
Minimal reproducible example on Rust playpen
供参考,我的编译器版本是:
$ rustc --version
rustc 1.1.0-dev (built 2015-04-26)
据我了解,您的原始代码在 T
上进行了参数化,但您有想要指定参数的方法。诀窍是 没有针对这些情况的通用 。相反,尝试为每个有趣的类型创建专门的实现:
// this is just an example. suppress unrelated warnings
#![allow(dead_code, unused_variables)]
struct Foobar<T> {
origin: T,
}
trait Orange {}
struct Grapefruit;
impl Orange for Grapefruit {}
impl Foobar<()> {
fn from_nowhere() -> Foobar<()> {
Foobar { origin: () }
}
}
impl<'a, F> Foobar<&'a mut F>
where F: Orange
{
fn from_orange(orange: &'a mut F) -> Foobar<&'a mut F> {
Foobar { origin: orange }
}
}
impl<F> Foobar<F>
where F: FnMut(u64) -> u64
{
fn from_callback(callback: F) -> Foobar<F> {
Foobar { origin: callback }
}
}
fn main() {
let mut fruit = Grapefruit;
// What I actually wanted to do
let a1 = Foobar::from_nowhere();
let b1 = Foobar::from_orange(&mut fruit);
let c1 = Foobar::from_callback(|x| x*x);
}
我正在为 C 库编写 Rust 绑定。它实现了一个可以从不同源实体构造的实体,可能在内部保存一些引用。我希望 Rust 类型执行安全的所有权策略,因此包装器结构是通用的,由存储引用的类型参数化。
struct Foobar<T> {
origin: T,
}
然后我为我的 Foobar
类型实现了一些构造函数。
impl<T> Foobar<T> {
fn from_nowhere() -> Foobar<()> {
Foobar { origin: () }
}
fn from_orange<F>(orange: &mut F) -> Foobar<&mut F>
where F: Orange
{
Foobar { origin: orange }
}
fn from_callback<F>(callback: F) -> Foobar<F>
where F: FnMut(u64) -> u64
{
Foobar { origin: callback }
}
}
问题来了:结构体和构造函数都是独立参数化的。虽然可以从其参数推断构造函数类型参数,但构造函数中未使用结构类型参数,因此无法推断。因此,调用构造函数的天真方法
let a = Foobar::from_nowhere();
let b = Foobar::from_orange(&mut fruit);
let c = Foobar::from_callback(|x| x*x);
混淆 rustc:
rustgen.rs:43:13: 43:33 error: unable to infer enough type information about `_`; type annotations required [E0282]
rustgen.rs:43 let a = Foobar::from_nowhere();
可以通过提供一些任意类型的参数来修复它:
let a = Foobar::<()>::from_nowhere();
let b = Foobar::<()>::from_orange(&mut fruit);
let c = Foobar::<()>::from_callback(|x| x*x);
...真是丑陋不堪。解决该问题的另一种方法是将构造函数转换为自由函数,尽管它(有点)不合常理。
问题是,我是不是遗漏了什么?该设计似乎在某种程度上存在缺陷。设计这种类型以仅使用一级泛型的正确方法是什么?
Minimal reproducible example on Rust playpen
供参考,我的编译器版本是:
$ rustc --version
rustc 1.1.0-dev (built 2015-04-26)
据我了解,您的原始代码在 T
上进行了参数化,但您有想要指定参数的方法。诀窍是 没有针对这些情况的通用 。相反,尝试为每个有趣的类型创建专门的实现:
// this is just an example. suppress unrelated warnings
#![allow(dead_code, unused_variables)]
struct Foobar<T> {
origin: T,
}
trait Orange {}
struct Grapefruit;
impl Orange for Grapefruit {}
impl Foobar<()> {
fn from_nowhere() -> Foobar<()> {
Foobar { origin: () }
}
}
impl<'a, F> Foobar<&'a mut F>
where F: Orange
{
fn from_orange(orange: &'a mut F) -> Foobar<&'a mut F> {
Foobar { origin: orange }
}
}
impl<F> Foobar<F>
where F: FnMut(u64) -> u64
{
fn from_callback(callback: F) -> Foobar<F> {
Foobar { origin: callback }
}
}
fn main() {
let mut fruit = Grapefruit;
// What I actually wanted to do
let a1 = Foobar::from_nowhere();
let b1 = Foobar::from_orange(&mut fruit);
let c1 = Foobar::from_callback(|x| x*x);
}