mirror of
https://github.com/nushell/nushell.git
synced 2025-02-23 05:51:28 +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",
|
"dirs",
|
||||||
"omnipath",
|
"omnipath",
|
||||||
"pwd",
|
"pwd",
|
||||||
|
"ref-cast",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -13,6 +13,7 @@ bench = false
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dirs = { workspace = true }
|
dirs = { workspace = true }
|
||||||
|
ref-cast = "1.0.23"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
omnipath = { workspace = true }
|
omnipath = { workspace = true }
|
||||||
|
@ -14,7 +14,7 @@ mod private {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A marker trait for the different kinds of path forms.
|
/// 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:
|
/// The list of path forms are:
|
||||||
/// - [`Any`]: a path with no invariants. It may be a relative or an absolute path.
|
/// - [`Any`]: a path with no invariants. It may be a relative or an absolute path.
|
||||||
/// - [`Relative`]: a strictly relative path.
|
/// - [`Relative`]: a strictly relative path.
|
||||||
|
@ -2,6 +2,7 @@ use crate::form::{
|
|||||||
Absolute, Any, Canonical, IsAbsolute, MaybeRelative, PathCast, PathForm, PathJoin, PathPush,
|
Absolute, Any, Canonical, IsAbsolute, MaybeRelative, PathCast, PathForm, PathJoin, PathPush,
|
||||||
PathSet, Relative,
|
PathSet, Relative,
|
||||||
};
|
};
|
||||||
|
use ref_cast::{ref_cast_custom, RefCastCustom};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::{Borrow, Cow},
|
borrow::{Borrow, Cow},
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
@ -45,8 +46,9 @@ use std::{
|
|||||||
/// But this may cause third-party code to use [`std::env::current_dir`] to resolve
|
/// 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
|
/// 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).
|
/// is not the case after using [`as_relative_std_path`](Path::as_relative_std_path).
|
||||||
|
#[derive(RefCastCustom)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Path<Form: PathForm = Any> {
|
pub struct Path<Form = Any> {
|
||||||
_form: PhantomData<Form>,
|
_form: PhantomData<Form>,
|
||||||
inner: std::path::Path,
|
inner: std::path::Path,
|
||||||
}
|
}
|
||||||
@ -162,11 +164,11 @@ impl<Form: PathForm> Path<Form> {
|
|||||||
/// Create a new path of any form without validating invariants.
|
/// Create a new path of any form without validating invariants.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new_unchecked<P: AsRef<OsStr> + ?Sized>(path: &P) -> &Self {
|
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));
|
debug_assert!(Form::invariants_satisfied(path));
|
||||||
// Safety: `Path<Form>` is a repr(transparent) wrapper around `std::path::Path`.
|
ref_cast(std::path::Path::new(path))
|
||||||
let path = std::path::Path::new(path.as_ref());
|
|
||||||
let ptr = std::ptr::from_ref(path) as *const Self;
|
|
||||||
unsafe { &*ptr }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempt to create a new [`Path`] from a reference of another type.
|
/// 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 {
|
impl DerefMut for PathBuf {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
// Safety: `Path<Form>` is a repr(transparent) wrapper around `std::path::Path`.
|
#[ref_cast_custom]
|
||||||
let path: &mut std::path::Path = &mut self.inner;
|
fn ref_cast<Form: PathForm>(path: &mut std::path::Path) -> &mut Path<Form>;
|
||||||
let ptr = std::ptr::from_mut(path) as *mut Path;
|
|
||||||
unsafe { &mut *ptr }
|
ref_cast(&mut self.inner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user