首页 > 技术文章 > Rust Borrow和AsRef的区别

mengsuenyan 2020-07-16 22:50 原文

Rust Borrow和AsRef的区别


AsRef/AsRefMutBorrow/BorrowMut具有相似的借语义, 但他们有如下的不同;

  • 任何类型T都实现了(blanket impl)Borrowtrait, 即Rust中任何实例都是可以被借用(&/&mut)的(当然这里任何是指满足语法语义规则的任何, 比如该实例没有其被其它实例&mut借用). 而AsRef只是实现了满足实现了AsRef<U>的类型&T&U的转换. 源码如下:;
///////////////////////////////////Borrow
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Borrow<T> for T {
    fn borrow(&self) -> &T {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> BorrowMut<T> for T {
    fn borrow_mut(&mut self) -> &mut T {
        self
    }
}

/////////////////////////////////// AsRef
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized, U: ?Sized> AsRef<U> for &T
where
    T: AsRef<U>,
{
    fn as_ref(&self) -> &U {
        <T as AsRef<U>>::as_ref(*self)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized, U: ?Sized> AsRef<U> for &mut T
where
    T: AsRef<U>,
{
    fn as_ref(&self) -> &U {
        <T as AsRef<U>>::as_ref(*self)
    }
}
  • Borrow还有一个潜在的语义是: 如果某个类型实现了Hash/Eq/Ord, 那么在Borrow实例上的Hash/Eq/Ord操作应该和该类型实例上的Hash/Eq/Ord操作是等效的, 如HashMap上的get接口实现对K的类型约束. 根据该潜在的语义, 如果只是借用某个结构struct中的某个域, 应该实现AsRef而不是Borrow;

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Borrow<T> for &T {
    fn borrow(&self) -> &T {
        &**self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Borrow<T> for &mut T {
    fn borrow(&self) -> &T {
        &**self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> BorrowMut<T> for &mut T {
    fn borrow_mut(&mut self) -> &mut T {
        &mut **self
    }
}

参考资料

推荐阅读