在Rust中是否有一种方法可以将类型标记为不可释放的?

4
我希望将允许丢弃类型的行为变成编译错误,必须将其遗忘。我的用例是用于表示某种句柄的类型,必须将其返回到源以进行清理。这样,API的用户就无法意外泄漏句柄。他们要么必须将句柄返回给其源,要么必须明确地遗忘它。在源中,相关资源将被清除并明确遗忘该句柄。

为什么不在构造函数中预先泄漏它并返回一个 'static 引用,而不是通过值构造它并依赖用户做正确的事情呢? - trent
2个回答

9
本文提到了 Rust中真正线性类型的痛苦。相关引用:
“我见过的一个极端选项是将drop()实现为abort("this value must be used")。 然后"proper consumers" mem::forget这个值,防止这个"destructor bomb"触发。这提供了动态版本的严格必须使用的值。虽然它仍然容易受到析构函数泄露的少数方式的影响, 但在实践中,这不是一个重要的问题。主要是因为它是动态的,而Rust用户想要静态验证。”
“最终,Rust缺乏对这种类型的"适当"支持。”
所以,假设您想要进行静态检查,则答案是否定的。

1
我对Rust并不是很熟悉,但是否可以将一个句柄包装在一个虚拟的“结构体”中,并使句柄源从该句柄结构体借用一些虚拟引用?这样,如果一个句柄被丢弃,那么源代码将生成“doesn't live long enough”错误,这并不是自描述的,但这种行为可以在注释中描述。 - Alexey Larionov
@AlexLarionov 是的,它必须是运行时错误。 - Peter Hall
谢谢,我得出了与放弃有关的相同结论,希望有一种像发送那样的特性可以将类型标记为不可丢弃。 - nate

1
您可以要求用户传递一个返回句柄的函数对象(FnOnce(Handle) -> Handle),只要没有其他创建句柄的方法。

从技术上讲,这确实会丢弃Handle,但有点作弊:) |h: Handle| { drop(h); let (_, rx) = mpsc::channel::<Handle>(); rx.recv().unwrap() } - Michał Trybus
@MichałTrybus 那不就相当于 |h: Handle| { drop(h); panic!() } 吗? - Solomon Ucko
当然,我本来就是想永久挂起它...: |h: Handle| { drop(h); let (tx, rx) = mpsc::channel::<Handle>(); rx.recv().unwrap() } :) - Michał Trybus
@MichałTrybus 哦,对不起,我看到了 unwrap 就匆忙下结论了。所以是 loop {}。基本上,它必须发散,不能正常返回。 - Solomon Ucko
1
没错,但我只是在吹毛求疵,因为在我的例子中,无论等待多久可能都没有意义,h 实际上被丢弃了。 - Michał Trybus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接