

为什么用 assert_eq 比较 string 和 &str 会成功?
source link: https://tingfei.art/posts/compare_string_and_str/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

为什么用 assert_eq 比较 string 和 &str 会成功?
昨天写代码的时候发现用 assert_eq 比较 string 和 &str 会成功,如下:
let s1 = String::from("hello");
let s2 = "hello";
assert_eq!(s1, s2);
凭直觉来讲,这不应该能通过,因为 string 和 &str 是两种类型,然后我觉得是 assert_eq 这个宏做了特殊处理,于是我又试了一下
let s1 = String::from("hello");
let s2 = "hello";
assert!(s1 == s2);
发现也没有问题,这说明和 assert_eq 没啥关系,于是我在 reddit 以及 Rust 中文社区提问,一个老哥的回答是:
String and &str cannot be compared at all, so Rust will look for ways to make the comparison possible. It will find that s1.deref() returns &str which obviously can be compared to &str (because Strings implement Deref<Target=str>) so it will automatically use that. This is called “deref coercion”.
简言之,他的理解是因为强制解引用多态(deref coercion)使得 s1 自动调用 deref() ,而其实现了 Deref <Target=str>
,所以返回 &str , 然后就能与 s2 相比较了。逻辑非常清晰,我都已经道谢了,但是后面证实这是不正确的,另一位老哥也对这种说法进行了严谨地反驳:
这个说法是错的,跟 Deref 没有直接的关系,你可以这样写:
// assert macro will print using debug format
#[derive(Debug)]
struct S {
inner: String,
}
impl S {
pub fn new(inner: &str) -> Self {
Self {
inner: inner.to_owned(),
}
}
}
impl std::cmp::PartialEq<&str> for S {
fn eq(&self, other: &&str) -> bool {
return self.inner.eq(other);
}
}
// comment for compile error
impl std::cmp::PartialEq<S> for &str {
fn eq(&self, _other: &S) -> bool {
return false;
}
}
fn main() {
let s = "hello";
let string = String::from("hello");
let fake_string = S::new("hello");
assert_eq!(string, s);
assert_eq!(fake_string, s);
assert_eq!(s, fake_string);
}
这里 S 没有实现任何 deref,但是还是可以通过编译。把
assert_eq
宏展开之后是这样的:
match (&s, &fake_string) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
{
::std::rt::begin_panic_fmt...
也就是说这里只调用了 lhs == rhs,只要实现了 PartialEq for Lhs 就可以了。 String 的文档里面两种顺序都实现了。
后面通过翻文档发现 String 和 str 确实互相实现了 PartialEq Trait,所以 String 和 &str 是可以直接比较的。
感谢 rustaceans 的热心解答。
Recommend
-
46
Change language: parse_str (PHP 4, PHP 5, PHP 7)parse_str — Parses the strin...
-
16
Introduction str_contains checks if a string is contained in another string and returns a boolean value (true/false) whether or not the string was found. The typical wa...
-
27
话说前几天我刚通过 mlcache 优化了热数据的问题,屁股还没坐热乎呢,就发现系统性能又下降了,本着自己挖的坑含泪也要填上的原则,我再一次开始了性能调优之旅。 ...
-
5
String str="abc" 一定会进入到字符串常量池吗? V2EX › 程序员 String str="abc" 一定会进入到字符串常量池吗? ...
-
6
What is Box<str> and how is it different from String in Rust? Jun 16, 2022 • Reading time: 13 minutes Today I and a friend went d...
-
5
作者:@apocelipes本文为作者原创,转载请注明出处:https://www.cnblogs.com/apocelipes/p/16910089.html
-
8
String String 类型的数据和基本类型不同,基本类型的长度是固定的,所以可以在栈上分配,而String类型是变长的,所以需要在堆上分配,所以String 类型实际上是一个指向堆的指针。他的结构和Vec很类似。从他的声明看也是一个u8的Vec
-
7
In this article, you'll learn the different methods of appending strings in Python. Another term commonly used when talking about appending strings is concatenation. So you'll often see these terms — append and concatenate — used interchang...
-
4
April 4, 2023 /
-
10
Dec 31, 2023 Arc<str> vs String, is Arc<str> really faster? I was watching The Primagen’s
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK