[英]To what extent does rust compiler auto match generic constraint?
Consider the following code for binary tree 考虑下面的二进制树代码
#[derive(Debug)]
struct Binary_Tree_Node<T: PartialOrd + Clone> {
left: Binary_Tree<T>,
value: T,
right: Binary_Tree<T>
}
#[derive(Debug)]
struct Binary_Tree<T: PartialOrd + Clone> {
node: Option<Box<Binary_Tree_Node<T>>>
}
impl <T: PartialOrd + Clone>Binary_Tree<T> {
fn new(value_to_insert: T) -> Binary_Tree<T> {
Binary_Tree{node:
Some(
Box::new(
Binary_Tree_Node{
left: Binary_Tree{node: None},
value: value_to_insert,
right: Binary_Tree{node: None}
}
)
)
}
}
fn map<F, U>(&self, f: F) -> Option<U>
where F: FnOnce(&Binary_Tree_Node<T>) -> U {
self.node.as_ref().map(|node| f(&**node))
// equivalent
//self.node.as_ref().map(|node| f(node))
}
}
let mut test1 = Binary_Tree::new(10);
println!("{:#?}", test1.map(|node| node.value < 2));
This line confuses me 这行使我感到困惑
self.node.as_ref().map(|node| f(node))
as I expect rust to throw compiler error 正如我期望的锈会引发编译器错误
self.node
is of type Option<Box<Binary_Tree_Node<T>>>
self.node
的类型为Option<Box<Binary_Tree_Node<T>>>
self.node.as_ref()
is of type Option<&Box<Binary_Tree_Node<T>>>
self.node.as_ref()
的类型为Option<&Box<Binary_Tree_Node<T>>>
node
in self.node.as_ref().map(|node| f(node))
is of type &Box<Binary_Tree_Node<T>>
node
在self.node.as_ref().map(|node| f(node))
的类型为&Box<Binary_Tree_Node<T>>
&Box<Binary_Tree_Node<T>>
is not equivalent to the generic constraint &Binary_Tree_Node<T>
&Box<Binary_Tree_Node<T>>
不等同于通用约束&Binary_Tree_Node<T>
The question is why both self.node.as_ref().map(|node| f(&**node))
and self.node.as_ref().map(|node| f(node))
work? 问题是为什么
self.node.as_ref().map(|node| f(&**node))
和self.node.as_ref().map(|node| f(node))
起作用?
This is a "Deref coercion", see nomicon Coercions : 这是“ Deref强制”,请参阅nomicon强制 :
Coercion is allowed between the following types:
以下类型之间允许强制转换:
- [...]
[...]
- Deref coercion: Expression
&x
of type&T
to&*x
of type&U
ifT
derefs toU
(ieT: Deref<Target=U>
)DEREF胁迫:表达式
&x
型的&T
到&*x
型的&U
如果T
derefs到U
(即T: Deref<Target=U>
Box<T>
implements Deref<Target=T>
, so &Box<T>
coerces automatically to &T
like you'd have written &*node
. Box<T>
实现Deref<Target=T>
,因此&Box<T>
自动Deref<Target=T>
为&T
就像您已经编写&*node
。
(I'm not sure what the &
in "Expression &x
" part is for, because we don't have a &
at coercion site and it still works - could be a typo or a bug) (我不确定“ Expression
&x
”部分中的&
是什么意思,因为我们在强制站点上没有&
,并且仍然有效-可能是拼写错误或错误)
Also works from &String
to &str
: Playground 也可以从
&String
到&str
: Playground
fn foo<T>(_v: T) {}
fn main() {
{
let v: &Box<i32> = &Box::new(5i32);
foo::<&i32>(v);
foo::<&i32>(&*v);
}
{
let v: &String = &String::from("abc");
foo::<&str>(v);
foo::<&str>(&*v);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.