在 Rust 中强制转换可变引用 -> 不可变引用 -> 可变引用是否有效

问题描述 投票:0回答:1

所以我知道将不可变引用转换为可变引用是UB。然而,如果不可变引用是从可变引用派生的,那么它是否仍然被认为是 UB,因为从技术上讲,内存应该已经被视为可变的?或者这仍然是 UB,因为事实上不可变引用曾经是可变的,完全不相关,并且考虑到从可变 -> 不可变的转换会消耗原始可变引用,它仍然会将引用视为不可变?

更具体地说,假设我有一个像这样的树结构:

pub struct Schema {
    pub name: String,
    pub fields: Vec<SchemaNode>,
    pub types: BTreeMap<String, ComplexType>,
}

pub struct SchemaNode {
    pub name: String,
    pub dtype: DType,
}

pub enum DType {
    Base(),
    Complex {
        name: String,
    },
}

pub struct ComplexType {
    pub children: Vec<SchemaNode>,
}

impl Schema {
    pub fn query(&self, query: &str) -> Option<&SchemaNode> {
        let mut fragments = query.split(".");

        let name = fragments.next()?;
        let mut node = self.fields.iter().filter(|n| n.name == name).next()?;

        // continue down if required
        for name in fragments {
            match &node.dtype {
                DType::Base => return None,
                DType::Complex { name: type_name } => {
                    node = self
                        .types
                        .get(type_name)?
                        .children
                        .iter()
                        .filter(|c| c.name == name)
                        .next()?;
                }
            };
        }

        Some(node)
    }
}

如果我想添加一个query_mut方法,这样做可以吗:

impl Schema {
    pub fn query_mut<'a>(&'a mut self, query: &str) -> Option<&'a mut SchemaNode> {
        let node = self.query(query)?;
        unsafe {
            let const_ptr = node as *const SchemaNode;
            let mut_ptr = const_ptr as *mut SchemaNode;
            mut_ptr.as_mut()
        }
    }
}

在这种情况下,我知道可以编写 query_mut,然后从 query_mut 派生查询,但由于它当前的结构,您会遇到可变性问题,因为 Schema.types 会在循环内多次借用。

rust borrow-checker
1个回答
0
投票

是的,这是无效的。

引用经济学

  • &
    转换为
    &mut
    是未定义的行为。虽然某些用法可能 出现安全,请注意,Rust 优化器可以自由地假设共享 引用在其生命周期内不会改变,因此这种转变将 与这些假设相冲突。所以:
    • &
      转换为
      &mut
      始终 未定义的行为。
    • 不,你做不到。
    • 不,你并不特别。

单独写一个

query_mut()
正确的方法。

© www.soinside.com 2019 - 2024. All rights reserved.