PAYATHON 2026

如何从 ra_ap_hir::Type 区分 *mut 与 *const 裸指针?

数据小陈

结论

根据问题给出的 0.0.318 接口与源码,Type 的公开接口存在缺口:内部保存了裸指针的 Mutability,但列出的接口没有将其返回给调用方。remove_raw_ptr()、as_reference() 和 attach_db 都无法获取这个信息。

这一限制与版本有关:已核对的 ra_ap_hir 0.0.358 文档公开了 is_mutable_raw_ptr() 和 as_raw_ptr(),可以考虑升级到包含这些方法的版本。如果必须保留 0.0.318,则需要修改依赖源码,或继续使用显示字符串作为临时兜底。这两个方法最早加入的版本尚不确定。Type 接口文档

支持新接口时,直接读取类型信息

在已提供上述方法的版本中,如果只需要判断是否为 *mut T,可以这样写:

fn is_mutable_raw_ptr(ty: &ra_ap_hir::Type<'_>) -> bool {
    ty.is_mutable_raw_ptr()
}

如果还需要指向的类型和可变性,可以使用:

if let Some((pointee, mutability)) = ty.as_raw_ptr() {
    // 在这里使用 pointee 和 mutability。
}

as_raw_ptr() 返回 None 表示当前类型不是裸指针。对于需要分别处理非裸指针、*const T 和 *mut T 的分析逻辑,它比单个布尔值更合适。升级时还需检查其他 ra_ap_* 依赖的兼容性,不能只替换方法调用。

必须使用 0.0.318 时,在依赖内部补接口

根据问题提供的 TyKind 表示,如果只需要布尔判断,可以在 ra_ap_hir 源码现有的 impl<'db> Type<'db> 中添加:

pub fn is_mutable_raw_ptr(&self) -> bool {
    matches!(
        self.ty.kind(),
        TyKind::RawPtr(_, hir_ty::next_solver::Mutability::Mut)
    )
}

这段代码沿用题中 is_mutable_reference() 对内部 Mutability 的访问方式,需要放在能够访问 self.ty 的依赖源码中,不能直接放进应用 crate。

在应用里定义扩展 trait 也无法绕过字段可见性,为外部类型新增固有方法同样不可行。可通过 fork 或本地补丁维护这个改动,并将其提交上游。

如果要补充 as_raw_ptr(),应参照同版本 as_reference() 的实现,同时返回 self.derived(ty) 和可变性。还要沿用该版本内部 Mutability 到公开 Mutability 的转换方式,不能因为名称相同就假定二者是同一个类型。

为什么现有尝试拿不到可变性

  • remove_raw_ptr() 只返回指向的类型,丢弃了外层指针的可变性。例如,*mut i32 和 *const i32 都会得到 i32。
  • as_reference() 匹配引用类型;裸指针对应另一种 TyKind 变体。
  • attach_db 提供数据库上下文,不会改变 Rust 的字段访问权限。
  • Type::walk() 的回调接收 Type,不会因此获得其私有内部表示。

显示字符串只能作为临时兜底

无法升级或修改依赖时,可以保留字符串方案,但建议明确处理“格式无法识别”的情况:

let raw_ptr_mutability: Option<bool> = if !ty.is_raw_ptr() {
    None
} else {
    let rendered = ty.display(db, display_target).to_string();
    if rendered.starts_with("*mut ") {
        Some(true)
    } else if rendered.starts_with("*const ") {
        Some(false)
    } else {
        None
    }
};

这里的 None 合并了“不是裸指针”和“显示格式未识别”两种情况。如果后续逻辑需要区分,应改用自定义枚举。不要把所有不匹配 *mut 的结果都当成 *const T。

显示输出用于类型展示,不应自行假定它是稳定的机器读取协议。兜底逻辑应固定依赖版本,并检查 *mut T、*const T、嵌套裸指针和类型别名等情况。判断嵌套类型时,还应明确需要的是最外层指针的可变性,还是逐层分析。

备注:内容仅供参考。