简体   繁体   English

rust编译器在何种程度上自动匹配泛型约束?

[英]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>> nodeself.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 if T derefs to U (ie T: 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&strPlayground

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM