仅用于借用检查的零宽度参考?
Zero width reference for borrow checking only?
我的目标是以零成本使用借用检查器在我的代码中强制执行不变量。但是,要使其成本为零,我似乎需要一个零宽度参考。这是上下文:
我想为一些对象创建一个工厂,用一种方法一次性使所有对象失效。
/// Example struct.
/// In my real code, there's stuff in here,
/// but its unnecessary for the question I'm asking.
struct Obj;
/// A struct that lets you build new `Obj`s
struct ObjFactory;
impl ObjFactory {
/// makes a new object
fn make(&self) -> Obj {
Obj
}
/// enforce that there are no objects from this ObjFactory
fn recall(&self) {
// ?????
}
}
我想要的规则与借用检查器执行的规则相同,所以我添加了一些虚拟引用,使借用检查器在编译时遵循不变性。
/// new placeholder struct that should take up no space
struct Dummy;
/// Example struct.
/// Now has a dummy reference so the compiler knows when to get mad
struct Obj<'a>(&'a Dummy);
/// A struct that lets you build new `Obj`s
struct ObjFactory {dummy: Dummy}
impl ObjFactory {
/// makes a new object
fn make(&self) -> Obj {
// let the `Obj` immutably borrow the dummy
Obj(&self.dummy)
}
/// enforce that there are no objects from this ObjFactory
fn recall(&mut self) {
// mutably borrow `dummy`, which means that Obj's can't borrow it anymore.
let _borrow = &mut self.dummy;
}
}
现在,编译器可以检测到不变量何时被破坏:
fn main() {
// make factory
let mut obj_factory = ObjFactory{dummy: Dummy};
// create an object
let obj = obj_factory.make();
// uh oh! no objects are allowed!
obj_factory.recall();
// obj lasts until the end of the function
core::mem::drop(obj);
}
当 recall
发生时,编译器正确检测到存在一个对象。
error[E0502]: cannot borrow `obj_factory` as mutable because it is also borrowed as immutable
--> src/main.rs:4:5
|
3 | let obj = obj_factory.make();
| ----------- immutable borrow occurs here
4 | obj_factory.recall();
| ^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
5 | core::mem::drop(obj);
| --- immutable borrow later used here
这完全符合我的要求;但是,这不是零成本。即使每个 Obj
的 dummy 宽度为零,它仍然在 Obj
:
中占据 space
print!("{}", std::mem::size_of::<Obj>()); // 8
我应该如何将 Obj
的 space 用法降低到 0
,同时让借用检查器强制执行 ObjFactory
不变量?
您可以使用 PhantomData
来获得具有生命周期的空类型:
use core::marker::PhantomData;
/// Example struct.
struct Obj<'a>(PhantomData<&'a ()>);
/// A struct that lets you build new `Obj`s
struct ObjFactory;
impl ObjFactory {
/// makes a new object
fn make(&self) -> Obj<'_> {
Obj(PhantomData) // the PhantomData has the same lifetime as `self`
}
/// enforce that there are no objects from this ObjFactory
fn recall(&mut self) {}
}
fn main() {
// make factory
let mut obj_factory = ObjFactory;
// create an object
let obj = obj_factory.make();
// uh oh! no objects are allowed!
obj_factory.recall();
// obj lasts until the end of the function
core::mem::drop(obj);
}
我的目标是以零成本使用借用检查器在我的代码中强制执行不变量。但是,要使其成本为零,我似乎需要一个零宽度参考。这是上下文:
我想为一些对象创建一个工厂,用一种方法一次性使所有对象失效。
/// Example struct.
/// In my real code, there's stuff in here,
/// but its unnecessary for the question I'm asking.
struct Obj;
/// A struct that lets you build new `Obj`s
struct ObjFactory;
impl ObjFactory {
/// makes a new object
fn make(&self) -> Obj {
Obj
}
/// enforce that there are no objects from this ObjFactory
fn recall(&self) {
// ?????
}
}
我想要的规则与借用检查器执行的规则相同,所以我添加了一些虚拟引用,使借用检查器在编译时遵循不变性。
/// new placeholder struct that should take up no space
struct Dummy;
/// Example struct.
/// Now has a dummy reference so the compiler knows when to get mad
struct Obj<'a>(&'a Dummy);
/// A struct that lets you build new `Obj`s
struct ObjFactory {dummy: Dummy}
impl ObjFactory {
/// makes a new object
fn make(&self) -> Obj {
// let the `Obj` immutably borrow the dummy
Obj(&self.dummy)
}
/// enforce that there are no objects from this ObjFactory
fn recall(&mut self) {
// mutably borrow `dummy`, which means that Obj's can't borrow it anymore.
let _borrow = &mut self.dummy;
}
}
现在,编译器可以检测到不变量何时被破坏:
fn main() {
// make factory
let mut obj_factory = ObjFactory{dummy: Dummy};
// create an object
let obj = obj_factory.make();
// uh oh! no objects are allowed!
obj_factory.recall();
// obj lasts until the end of the function
core::mem::drop(obj);
}
当 recall
发生时,编译器正确检测到存在一个对象。
error[E0502]: cannot borrow `obj_factory` as mutable because it is also borrowed as immutable
--> src/main.rs:4:5
|
3 | let obj = obj_factory.make();
| ----------- immutable borrow occurs here
4 | obj_factory.recall();
| ^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
5 | core::mem::drop(obj);
| --- immutable borrow later used here
这完全符合我的要求;但是,这不是零成本。即使每个 Obj
的 dummy 宽度为零,它仍然在 Obj
:
print!("{}", std::mem::size_of::<Obj>()); // 8
我应该如何将 Obj
的 space 用法降低到 0
,同时让借用检查器强制执行 ObjFactory
不变量?
您可以使用 PhantomData
来获得具有生命周期的空类型:
use core::marker::PhantomData;
/// Example struct.
struct Obj<'a>(PhantomData<&'a ()>);
/// A struct that lets you build new `Obj`s
struct ObjFactory;
impl ObjFactory {
/// makes a new object
fn make(&self) -> Obj<'_> {
Obj(PhantomData) // the PhantomData has the same lifetime as `self`
}
/// enforce that there are no objects from this ObjFactory
fn recall(&mut self) {}
}
fn main() {
// make factory
let mut obj_factory = ObjFactory;
// create an object
let obj = obj_factory.make();
// uh oh! no objects are allowed!
obj_factory.recall();
// obj lasts until the end of the function
core::mem::drop(obj);
}