[英]Is this mem::transmute::<&str, &'static str>(k) safe?
I'm looking at this code which is a very simple library with just one file and mostly tests, so it's short.我正在查看这个代码,它是一个非常简单的库,只有一个文件并且主要是测试,所以它很短。 There's a struct that I'm trying to understand:
我试图理解一个结构:
pub struct ChallengeFields(HashMap<UniCase<CowStr>, (String, Quote)>);
struct CowStr(Cow<'static, str>);
There's a line where it does有一条线
pub fn get(&self, k: &str) -> Option<&String> {
self.0
.get(&UniCase(CowStr(Cow::Borrowed(unsafe {
mem::transmute::<&str, &'static str>(k)
}))))
.map(|&(ref s, _)| s)
}
I'm annoyed by this unsafe
operation.我对这种
unsafe
的操作感到恼火。 I think CowStr
is a Cow
with 'static
lifetime otherwise it'd be hard or impossible to store str
s inside the map.我认为
CowStr
是具有'static
生命周期”的Cow
,否则很难或不可能将str
存储在 map 内。 Because of that, when I try to get something inside this map, the str
in question has to have 'static
lifetime.正因为如此,当我试图在这个 map 中获取一些东西时,有问题的
str
必须具有'static
生命周期”。 This is the reason for the transmute
, right?这就是
transmute
的原因吧? If so, why simply not use String
, so we can get rid of lifetimes and thus transmute
?如果是这样,为什么干脆不使用
String
,这样我们就可以摆脱生命周期,从而transmute
? I don't like unsafe
, and reading about transmute
it looks very unsafe.我不喜欢
unsafe
,并且阅读有关transmute
的内容看起来非常不安全。
Also, I don't see why Cow
is needed at all.另外,我根本不明白为什么需要
Cow
。
I think
CowStr
is aCow
with'static
lifetime otherwise it'd be hard or impossible to store strs inside the map.我认为
CowStr
是具有'static
生命周期”的Cow
,否则很难或不可能将 strs 存储在 map 内。
Well yes and no, you can store &'static str
inside a hashmap with no issue, the problem is that you can't store both &'static str
and String
.好吧,是也不是,您可以毫无问题地将
&'static str
存储在 hashmap 中,问题是您不能同时存储&'static str
和String
。
Am I rigth?
我说得对吗? If so, why simply not use String, so we can get rid of lifetimes and thus transmute?
如果是这样,为什么干脆不使用字符串,这样我们就可以摆脱生命周期,从而转化?
I assume that is an optimisation: with String
you'd have to create an allocation every time you want to insert a challenge in the map, but if the overwhelming majority of challenge names would be Digest
and Basic
then that's a waste of time (and memory but mostly time), but at the same time you'd have to support String
for custom auth schemes.我认为这是一种优化:使用
String
时,每次您想在 map 中插入挑战时都必须创建分配,但如果绝大多数挑战名称是Digest
和Basic
,那么这是浪费时间(并且memory 但主要是时间),但同时您必须支持自定义身份验证方案的String
。
Now maybe in the grand scheme of things this is not an optimisation which actually matter and it'd be better off not doing that, I couldn't tell you.现在,也许从总体上看,这并不是一个真正重要的优化,最好不要这样做,我不能告诉你。
I don't like unsafe, and reading about transmute it looks very unsafe.
我不喜欢不安全的,并且阅读有关 transmute 的内容看起来非常不安全。
It's a debatable thing to do, but in this case it's "safe", in the sense that the reference is valid for the entirety of the HashMap::get
call and we know that that call doesn't keep the reference alive (it's reliance on an implementation detail which is a bit risky, but the odds that that would change are basically nil as it wouldn't make much sense).这是一件值得商榷的事情,但在这种情况下它是“安全的”,因为引用对整个
HashMap::get
调用有效,我们知道该调用不会使引用保持活动状态(它是依赖在一个有点冒险的实现细节上,但改变的可能性基本上为零,因为它没有多大意义)。
Extending lifetimes is not in-and-of-itself UB (the mem::transmute
documentation literally provides an example doing that), but requires care as you must avoid it causing UBs (the most likely being a dangling reference).延长生命周期本身并不是 UB(
mem::transmute
文档确实提供了一个这样做的示例),但需要小心,因为您必须避免它导致 UB(最有可能是悬空引用)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.