mirror of
https://github.com/nushell/nushell.git
synced 2025-02-22 05:21:44 +01:00
Use ref-cast
crate to remove some unsafe
(#14897)
# Description In a few places, `nu-path` uses `unsafe` to do reference casts. This PR adds the [`ref-cast`](https://crates.io/crates/ref-cast) crate to do reference casts in a "safe" manner.
This commit is contained in:
parent
f46f8b286b
commit
7ea4895513
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3928,6 +3928,7 @@ dependencies = [
|
||||
"dirs",
|
||||
"omnipath",
|
||||
"pwd",
|
||||
"ref-cast",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -13,6 +13,7 @@ bench = false
|
||||
|
||||
[dependencies]
|
||||
dirs = { workspace = true }
|
||||
ref-cast = "1.0.23"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
omnipath = { workspace = true }
|
||||
@ -21,4 +22,4 @@ omnipath = { workspace = true }
|
||||
pwd = { workspace = true }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
workspace = true
|
||||
|
@ -14,7 +14,7 @@ mod private {
|
||||
}
|
||||
|
||||
/// A marker trait for the different kinds of path forms.
|
||||
/// Each form has its own invariants that are guaranteed be upheld.
|
||||
/// Each form has its own invariants that are guaranteed to be upheld.
|
||||
/// The list of path forms are:
|
||||
/// - [`Any`]: a path with no invariants. It may be a relative or an absolute path.
|
||||
/// - [`Relative`]: a strictly relative path.
|
||||
|
@ -2,6 +2,7 @@ use crate::form::{
|
||||
Absolute, Any, Canonical, IsAbsolute, MaybeRelative, PathCast, PathForm, PathJoin, PathPush,
|
||||
PathSet, Relative,
|
||||
};
|
||||
use ref_cast::{ref_cast_custom, RefCastCustom};
|
||||
use std::{
|
||||
borrow::{Borrow, Cow},
|
||||
cmp::Ordering,
|
||||
@ -45,8 +46,9 @@ use std::{
|
||||
/// But this may cause third-party code to use [`std::env::current_dir`] to resolve
|
||||
/// the path which is almost always incorrect behavior. Extra care is needed to ensure that this
|
||||
/// is not the case after using [`as_relative_std_path`](Path::as_relative_std_path).
|
||||
#[derive(RefCastCustom)]
|
||||
#[repr(transparent)]
|
||||
pub struct Path<Form: PathForm = Any> {
|
||||
pub struct Path<Form = Any> {
|
||||
_form: PhantomData<Form>,
|
||||
inner: std::path::Path,
|
||||
}
|
||||
@ -162,11 +164,11 @@ impl<Form: PathForm> Path<Form> {
|
||||
/// Create a new path of any form without validating invariants.
|
||||
#[inline]
|
||||
fn new_unchecked<P: AsRef<OsStr> + ?Sized>(path: &P) -> &Self {
|
||||
#[ref_cast_custom]
|
||||
fn ref_cast<Form: PathForm>(path: &std::path::Path) -> &Path<Form>;
|
||||
|
||||
debug_assert!(Form::invariants_satisfied(path));
|
||||
// Safety: `Path<Form>` is a repr(transparent) wrapper around `std::path::Path`.
|
||||
let path = std::path::Path::new(path.as_ref());
|
||||
let ptr = std::ptr::from_ref(path) as *const Self;
|
||||
unsafe { &*ptr }
|
||||
ref_cast(std::path::Path::new(path))
|
||||
}
|
||||
|
||||
/// Attempt to create a new [`Path`] from a reference of another type.
|
||||
@ -1900,10 +1902,10 @@ impl<Form: PathForm> Deref for PathBuf<Form> {
|
||||
impl DerefMut for PathBuf {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
// Safety: `Path<Form>` is a repr(transparent) wrapper around `std::path::Path`.
|
||||
let path: &mut std::path::Path = &mut self.inner;
|
||||
let ptr = std::ptr::from_mut(path) as *mut Path;
|
||||
unsafe { &mut *ptr }
|
||||
#[ref_cast_custom]
|
||||
fn ref_cast<Form: PathForm>(path: &mut std::path::Path) -> &mut Path<Form>;
|
||||
|
||||
ref_cast(&mut self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user