Skip to content

Commit

Permalink
add DerefMut for Utf8PathBuf
Browse files Browse the repository at this point in the history
Also add a miri check for unsafe code.

Resolves camino-rs#57.
  • Loading branch information
sunshowers committed Mar 10, 2023
1 parent 1abbc37 commit 7247ba7
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 2 deletions.
36 changes: 35 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,19 @@ jobs:
matrix:
os: [ ubuntu-latest, macos-latest, windows-latest ]
# 1.34 is the MSRV, and the other versions add new features through build.rs.
# The nightly versions are used to ensure that build.rs's version detection is compatible
# with them:
# nightly-2022-06-17 is the last toolchain before `try_reserve_2` was stabilized.
rust-version: [ 1.34, 1.44, 1.56, nightly-2022-06-17, 1.63, stable ]
# nightly-2022-12-14 is the last toolchain before `path_buf_deref_mut` was stabilized.
rust-version:
- 1.34
- 1.44
- 1.56
- nightly-2022-06-17
- 1.63
- nightly-2022-12-14
- 1.68
- stable
exclude:
# These versions started failing with "archive member 'lib.rmeta' with length 26456 is not
# mach-o or llvm bitcode file".
Expand All @@ -58,6 +69,13 @@ jobs:
- uses: dtolnay/rust-toolchain@v1
with:
toolchain: ${{ matrix.rust-version }}
- name: Disable sparse registries on nightly-2022-12-14
# Sparse registries are experimental on this nightly, but are enabled by
# dtolnay/rust-toolchain.
if: matrix.rust-version == 'nightly-2022-12-14'
shell: bash
run: |
echo CARGO_REGISTRIES_CRATES_IO_PROTOCOL=git >> $GITHUB_ENV
- name: Build the library
run: cargo build
- name: Test
Expand All @@ -70,3 +88,19 @@ jobs:
# Some optional features are not compatible with earlier versions
if: ${{ matrix.rust-version == 'stable' }}
run: cargo test --workspace --all-features

miri:
name: Check unsafe code against miri
runs-on: ubuntu-latest
env:
RUSTFLAGS: -D warnings
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@v1
with:
toolchain: nightly
components: rust-src, miri
- name: Test the library
run: cargo miri test
env:
MIRIFLAGS: -Zmiri-disable-isolation
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

### Added

- Implement `DerefMut` for `Utf8PathBuf` on Rust 1.68 and above.

## [1.1.3] - 2023-02-21

### Added
Expand Down
11 changes: 10 additions & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,22 @@ fn main() {
if compiler.minor >= 56 {
println!("cargo:rustc-cfg=shrink_to");
}
// Stable and beta 1.63 have a stable try_reserve_2.
// NOTE: the below checks use == rather than `matches!`. This is because `matches!` isn't stable
// on Rust 1.34.
// try_reserve_2 was added in a 1.63 nightly.
if (compiler.minor >= 63
&& (compiler.channel == ReleaseChannel::Stable || compiler.channel == ReleaseChannel::Beta))
|| compiler.minor >= 64
{
println!("cargo:rustc-cfg=try_reserve_2");
}
// path_buf_deref_mut was added in a 1.68 nightly.
if (compiler.minor >= 68
&& (compiler.channel == ReleaseChannel::Stable || compiler.channel == ReleaseChannel::Beta))
|| compiler.minor >= 69
{
println!("cargo:rustc-cfg=path_buf_deref_mut");
}
}

struct Compiler {
Expand Down
12 changes: 12 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,13 @@ impl Deref for Utf8PathBuf {
}
}

#[cfg(path_buf_deref_mut)]
impl std::ops::DerefMut for Utf8PathBuf {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { Utf8Path::assume_utf8_mut(&mut self.0) }
}
}

impl fmt::Debug for Utf8PathBuf {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
Expand Down Expand Up @@ -1457,6 +1464,11 @@ impl Utf8Path {
// *const Path to a *const Utf8Path is valid.
&*(path as *const Path as *const Utf8Path)
}

#[cfg(path_buf_deref_mut)]
unsafe fn assume_utf8_mut(path: &mut Path) -> &mut Utf8Path {
&mut *(path as *mut Path as *mut Utf8Path)
}
}

impl Clone for Box<Utf8Path> {
Expand Down
8 changes: 8 additions & 0 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,11 @@ where
{
let _ = orig.into();
}

#[cfg(path_buf_deref_mut)]
#[test]
fn test_deref_mut() {
// This test is mostly for miri.
let mut path_buf = Utf8PathBuf::from("foobar");
let _: &mut Utf8Path = &mut path_buf;
}

0 comments on commit 7247ba7

Please sign in to comment.