当类型在结构定义中明确指定时,无法推断类型参数 T 的类型
Cannot infer type for type parameter T, when the type is explicitly specified in a struct definition
我有一个结构定义,其中包括以下字段:
pub struct Separated<'a, I, T>
{
..., // other fields,
separated: NonNull<dyn 'a + Iterator<Item = T>>,
}
不久之后,在其构造函数中,我尝试将该字段初始化为悬挂指针:
let sep = Separated {
..., // other fields
separated: NonNull::dangling(),
};
奇怪的是,这会产生此错误:
error[E0282]: type annotations needed
|
16 | separated: NonNull::dangling(),
| ^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
那个领域没有什么神秘的;它的类型在结构定义中明确设置。我不明白为什么类型推断器无法推断出合适的类型来注入。
可以在下面找到产生此错误的最少 20 行示例,并且 on the playground:
use std::pin::Pin;
use std::ptr::NonNull;
pub struct Separated<'a, T> {
t: &'a T,
separated: NonNull<dyn 'a + Iterator<Item = T>>,
}
impl<'a, T> Separated<'a, T>
where
T: 'a + Copy + PartialEq,
{
fn new(t: &'a T) -> Pin<Box<Self>> {
let sep = Separated {
t,
separated: NonNull::dangling(),
};
unimplemented!()
}
}
我确实需要 separated
成为指向 trait 对象的指针而不是单态类型:它将包含的真正 trait 对象由一堆迭代器组合器组成,包括像 Map
和 TakeWhile
,它们的类型包括函数指针,因此无法命名。
NonNull::dangling
不是参数函数:NonNull<T>
结构是参数化的,但这个函数不是。因此,我不能只是用涡轮鱼来解决这个问题。我完全不确定我将如何提供类型注释。
上下文,如果有用的话:我走这条路的全部原因是我试图创建一个迭代器组合器,为所有适当的迭代器自动实现,它在原点的每个 N 元素之间注入一个元素迭代器。对于单个迭代器来说并不难完成,但作为通用组合器更难完成,因为 Itertools 的 chunks()
组合器生成的 IntoChunks
结构本身不是迭代器,只是一个结构实现IntoIterator
。因此,我们需要跟踪 IntoChunks
结构以及它产生的迭代器。
我采用的方法是创建一个自引用结构 Separated
,其中包含这两个结构。假设结构始终固定,这应该是安全的。然后我 impl Iterator for Separated
将 next
调用推迟到 self.separated
。
根据标准文档,NonNull::dangling()
的定义是这样的:
impl<T> NonNull<T> {
pub const fn dangling() -> NonNull<T> {
/* ... */
}
}
并且在您的代码中,您在表达式类型为 NonNull<dyn 'a + Iterator<Item = T>>
的地方使用它,因此 return 值必须具有此类型。
这里的微妙之处在于泛型类型参数具有隐式 Sized
绑定(除非它具有 ?Sized
绑定)。因此,由于 NonNull::dangling
的实现没有 ?Sized
绑定,Rust 将根据这些要求尝试推断 NonNull
的类型参数:
- 因为
NonNull::<T>::dangling()
方法没有绑定T: ?Sized
,它只针对大小类型T
实现,类型参数必须大小
- 类型参数必须是
dyn 'a + Iterator<Item = T>
.
但是,由于特征对象(“dyn Trait
类型”)没有大小,Rust 不可能同时满足这两个要求,因此 "cannot infer type for type parameter T
".
事实上,通过将类型显式添加到您的 playground 示例中,您会收到一条不同的错误消息,该消息更明确地说明了问题:
let sep = Separated::<'a, T> {
t,
separated: NonNull::<dyn 'a + Iterator<Item = T>>::dangling(),
};
error[E0599]: no function or associated item named `dangling` found for type `std::ptr::NonNull<(dyn std::iter::Iterator<Item = T> + 'a)>` in the current scope
--> src/lib.rs:16:64
|
16 | separated: NonNull::<dyn 'a + Iterator<Item = T>>::dangling(),
| ^^^^^^^^ function or associated item not found in `std::ptr::NonNull<(dyn std::iter::Iterator<Item = T> + 'a)>`
|
= note: the method `dangling` exists but the following trait bounds were not satisfied:
`dyn std::iter::Iterator<Item = T> : std::marker::Sized`
我有一个结构定义,其中包括以下字段:
pub struct Separated<'a, I, T>
{
..., // other fields,
separated: NonNull<dyn 'a + Iterator<Item = T>>,
}
不久之后,在其构造函数中,我尝试将该字段初始化为悬挂指针:
let sep = Separated {
..., // other fields
separated: NonNull::dangling(),
};
奇怪的是,这会产生此错误:
error[E0282]: type annotations needed
|
16 | separated: NonNull::dangling(),
| ^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
那个领域没有什么神秘的;它的类型在结构定义中明确设置。我不明白为什么类型推断器无法推断出合适的类型来注入。
可以在下面找到产生此错误的最少 20 行示例,并且 on the playground:
use std::pin::Pin;
use std::ptr::NonNull;
pub struct Separated<'a, T> {
t: &'a T,
separated: NonNull<dyn 'a + Iterator<Item = T>>,
}
impl<'a, T> Separated<'a, T>
where
T: 'a + Copy + PartialEq,
{
fn new(t: &'a T) -> Pin<Box<Self>> {
let sep = Separated {
t,
separated: NonNull::dangling(),
};
unimplemented!()
}
}
我确实需要 separated
成为指向 trait 对象的指针而不是单态类型:它将包含的真正 trait 对象由一堆迭代器组合器组成,包括像 Map
和 TakeWhile
,它们的类型包括函数指针,因此无法命名。
NonNull::dangling
不是参数函数:NonNull<T>
结构是参数化的,但这个函数不是。因此,我不能只是用涡轮鱼来解决这个问题。我完全不确定我将如何提供类型注释。
上下文,如果有用的话:我走这条路的全部原因是我试图创建一个迭代器组合器,为所有适当的迭代器自动实现,它在原点的每个 N 元素之间注入一个元素迭代器。对于单个迭代器来说并不难完成,但作为通用组合器更难完成,因为 Itertools 的 chunks()
组合器生成的 IntoChunks
结构本身不是迭代器,只是一个结构实现IntoIterator
。因此,我们需要跟踪 IntoChunks
结构以及它产生的迭代器。
我采用的方法是创建一个自引用结构 Separated
,其中包含这两个结构。假设结构始终固定,这应该是安全的。然后我 impl Iterator for Separated
将 next
调用推迟到 self.separated
。
根据标准文档,NonNull::dangling()
的定义是这样的:
impl<T> NonNull<T> { pub const fn dangling() -> NonNull<T> { /* ... */ } }
并且在您的代码中,您在表达式类型为 NonNull<dyn 'a + Iterator<Item = T>>
的地方使用它,因此 return 值必须具有此类型。
这里的微妙之处在于泛型类型参数具有隐式 Sized
绑定(除非它具有 ?Sized
绑定)。因此,由于 NonNull::dangling
的实现没有 ?Sized
绑定,Rust 将根据这些要求尝试推断 NonNull
的类型参数:
- 因为
NonNull::<T>::dangling()
方法没有绑定T: ?Sized
,它只针对大小类型T
实现,类型参数必须大小 - 类型参数必须是
dyn 'a + Iterator<Item = T>
.
但是,由于特征对象(“dyn Trait
类型”)没有大小,Rust 不可能同时满足这两个要求,因此 "cannot infer type for type parameter T
".
事实上,通过将类型显式添加到您的 playground 示例中,您会收到一条不同的错误消息,该消息更明确地说明了问题:
let sep = Separated::<'a, T> {
t,
separated: NonNull::<dyn 'a + Iterator<Item = T>>::dangling(),
};
error[E0599]: no function or associated item named `dangling` found for type `std::ptr::NonNull<(dyn std::iter::Iterator<Item = T> + 'a)>` in the current scope
--> src/lib.rs:16:64
|
16 | separated: NonNull::<dyn 'a + Iterator<Item = T>>::dangling(),
| ^^^^^^^^ function or associated item not found in `std::ptr::NonNull<(dyn std::iter::Iterator<Item = T> + 'a)>`
|
= note: the method `dangling` exists but the following trait bounds were not satisfied:
`dyn std::iter::Iterator<Item = T> : std::marker::Sized`