Skip to content

Commit

Permalink
Enable crate to be used with the stable compiler (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
dpaoliello authored Mar 15, 2023
1 parent 784001f commit a99eacc
Show file tree
Hide file tree
Showing 9 changed files with 462 additions and 263 deletions.
32 changes: 5 additions & 27 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,39 +26,17 @@ jobs:
target: x86_64-unknown-linux-gnu
runs-on: ${{ matrix.os }}
env:
RUSTC_BOOTSTRAP: 1
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Run tests
run: cargo test --locked

- name: Clippy
run: cargo clippy --locked -- -D warnings

- name: Check formatting
run: cargo fmt --check

- name: Check docs
run: cargo doc --locked
env:
RUSTDOCFLAGS: -D warnings
- name: Update Rust toolchain
run: rustup update

- name: Add the rust-src component
run: rustup component add rust-src --toolchain stable-${{ matrix.target }}

- name: Build with no_global_oom_handling
run: cargo build --locked -Z build-std=core,alloc --target ${{ matrix.target }} -Z sparse-registry
env:
RUSTFLAGS: --cfg no_global_oom_handling

- name: Install miri
run: rustup toolchain install nightly --component miri

- name: Setup miri
run: cargo +nightly miri setup

- name: Run tests under miri
run: cargo +nightly miri test
- name: Run build script
shell: pwsh
run: .\build.ps1 -BuildLocked
11 changes: 10 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
[package]
name = "fallible_vec"
description = "Fallible allocation functions for the Rust standard library's `Vec` type."
version = "0.2.0"
version = "0.3.0"
edition = "2021"
license-file = "LICENSE"
repository = "https://github.com/microsoft/rust_fallible_vec"
readme = "README.md"
categories = ["embedded", "memory-management", "no-std"]
keywords = ["vec", "fallible", "collections", "no_std"]

[dependencies]
static_assertions = "1.1"

[features]
default = ["allocator_api", "use_unstable_apis"]
allocator_api = []
use_unstable_apis = []
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Fallible allocation functions for the Rust standard library's [`alloc::vec::Vec`
These functions are designed to be usable with `#![no_std]`, `#[cfg(no_global_oom_handling)]` (see
<https://github.com/rust-lang/rust/pull/84266>) enabled and Allocators (see <https://github.com/rust-lang/wg-allocators>).

By default this crate requires the nightly compiler, but the stable compiler can be used if all
features are disabled (i.e., specifying [`default-features = false` for the dependency](https://doc.rust-lang.org/cargo/reference/features.html#the-default-feature)).

## Usage

The recommended way to add these functions to `Vec` is by adding a `use` declaration for the
Expand Down Expand Up @@ -63,7 +66,8 @@ Comparing `fallible_vec` to [`fallible_collections`](https://crates.io/crates/fa
|-------------------------------------------|:---------------------:|:-----------------------------:|
| Supports `no_std` | X | X |
| Supports `#[cfg(no_global_oom_handling)]` | X | |
| Requires nightly | X | |
| Requires nightly rust compiler by default | X | |
| Supports stable rust compiler | X | X |
| `vec::try_append` | | X |
| `vec::try_extend` | X | |
| `vec::try_extend_from_slice` | X | X |
Expand All @@ -86,6 +90,17 @@ Comparing `fallible_vec` to [`fallible_collections`](https://crates.io/crates/fa
| `HashMap::*` | | X |
| `try_format!` | | X |

## Building locally

The recommended way to build locally is to use the `build.ps1` script: this will build the crate
using all feature combinations, run tests, check formatting, run clippy and build with `#[cfg(no_global_oom_handling)]`
enabled.

In order to run this script you'll need:
* [PowerShell 7+](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell)
* [Rust](https://rustup.rs/)
* Including the [`rust-src` component](https://rust-lang.github.io/rustup/concepts/components.html).

## Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a
Expand Down
52 changes: 43 additions & 9 deletions build.ps1
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
#Requires -Version 7

<#
.SYNOPSIS
Builds the `fallible_vec` crate, runs tests, checks formatting, runs clippy.
.PARAMETER BuildLocked
Adds `--locked` to the build commands to prevent the `Cargo.lock` file from being updated. This is
useful for CI builds.
.NOTES
See README.md for details on the environment that this script expects.
#>
param (
[Parameter(Mandatory = $false)]
[switch]
$BuildLocked
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

function Invoke-CheckExitCode([scriptblock]$ScriptBlock) {
$lockedArg = $BuildLocked ? '--locked' : $null

function Invoke-CheckExitCode([string] $Description, [scriptblock]$ScriptBlock) {
Write-Host "==== $Description ===="
& $ScriptBlock
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
Expand Down Expand Up @@ -31,23 +53,32 @@ Invoke-WithEnvironment `
'env:RUSTC_BOOTSTRAP' = '1';
# Fail 'cargo doc' on warnings.
'env:RUSTDOCFLAGS' = '-D warnings';
# Fail 'cargo build' on warnings.
'env:RUSTFLAGS' = '-D warnings';
} `
-ScriptBlock {
#
# Check that enabling various feature combinations works.
#
Invoke-CheckExitCode 'Build default' { cargo build $lockedArg }
Invoke-CheckExitCode 'Build allocator_api only' { cargo build $lockedArg --no-default-features --features allocator_api }
Invoke-CheckExitCode 'Build use_unstable_apis only' { cargo build $lockedArg --no-default-features --features use_unstable_apis }

#
# Run tests
#
Invoke-CheckExitCode { cargo test --locked }
Invoke-CheckExitCode 'Test' { cargo test --locked }

#
# Lint and check formatting.
#
Invoke-CheckExitCode { cargo clippy --locked -- -D warnings }
Invoke-CheckExitCode { cargo fmt --check }
Invoke-CheckExitCode 'Clippy' { cargo clippy --locked -- -D warnings }
Invoke-CheckExitCode 'Check format' { cargo fmt --check }

#
# Check docs
#
Invoke-CheckExitCode { cargo doc --locked }
Invoke-CheckExitCode 'Check docs' { cargo doc --locked }

#
# Verify that we can build with #[cfg(no_global_oom_handling)] enabled.
Expand All @@ -71,11 +102,14 @@ Invoke-WithEnvironment `
'env:RUSTFLAGS' = '--cfg no_global_oom_handling';
} `
-ScriptBlock {
Invoke-CheckExitCode { cargo build --locked -Z build-std=core,alloc --target $target }
Invoke-CheckExitCode 'Build no_global_oom_handling' { cargo build $lockedArg -Z build-std=core,alloc --target $target }
}
}

# Build with no features enabled (should work on the non-nightly compiler).
Invoke-CheckExitCode 'Build no features' { cargo build $lockedArg --no-default-features }

# Run tests under miri
Invoke-CheckExitCode { rustup toolchain install nightly --component miri }
Invoke-CheckExitCode { cargo +nightly miri setup }
Invoke-CheckExitCode { cargo +nightly miri test }
Invoke-CheckExitCode 'Install miri' { rustup toolchain install nightly --component miri }
Invoke-CheckExitCode 'Setup miti' { cargo +nightly miri setup }
Invoke-CheckExitCode 'Miri test' { cargo +nightly miri test }
7 changes: 6 additions & 1 deletion src/collect.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::FallibleVec;
use alloc::{collections::TryReserveError, vec::Vec};
use crate::TryReserveError;
use alloc::vec::Vec;

#[cfg(feature = "allocator_api")]
use core::alloc::Allocator;

/// Fallible allocations equivalents for [`Iterator::collect`].
Expand All @@ -20,6 +23,7 @@ pub trait TryCollect<T> {
/// assert_eq!(vec, [2, 4, 6, 8, 10]);
/// # Ok::<(), std::collections::TryReserveError>(())
/// ```
#[cfg(feature = "allocator_api")]
fn try_collect_in<A: Allocator>(self, alloc: A) -> Result<Vec<T, A>, TryReserveError>;

/// Attempts to collect items from an iterator into a vector.
Expand All @@ -43,6 +47,7 @@ impl<T, I> TryCollect<T> for I
where
I: IntoIterator<Item = T>,
{
#[cfg(feature = "allocator_api")]
fn try_collect_in<A: Allocator>(self, alloc: A) -> Result<Vec<T, A>, TryReserveError> {
let mut vec = Vec::new_in(alloc);
vec.try_extend(self.into_iter())?;
Expand Down
73 changes: 73 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use core::alloc::Layout;

#[allow(dead_code)]
#[cfg(any(test, not(feature = "use_unstable_apis")))]
mod internal {
// Forked from the Rust Standard Library: library/alloc/src/collections/mod.rs
use super::*;

/// The error type for `try_reserve` methods.
pub struct TryReserveError {
pub kind: TryReserveErrorKind,
}

/// Details of the allocation that caused a `TryReserveError`
pub enum TryReserveErrorKind {
/// Error due to the computed capacity exceeding the collection's maximum
/// (usually `isize::MAX` bytes).
CapacityOverflow,

/// The memory allocator returned an error
AllocError {
/// The layout of allocation request that failed
layout: Layout,
non_exhaustive: (),
},
}

pub fn build_error_from_layout(layout: Layout) -> alloc::collections::TryReserveError {
static_assertions::assert_eq_size!(
alloc::collections::TryReserveError,
internal::TryReserveError
);
unsafe {
core::mem::transmute(internal::TryReserveError {
kind: internal::TryReserveErrorKind::AllocError {
layout,
non_exhaustive: (),
},
})
}
}
}

#[cfg(feature = "use_unstable_apis")]
fn build_error_from_layout(layout: Layout) -> alloc::collections::TryReserveError {
alloc::collections::TryReserveErrorKind::AllocError {
layout,
non_exhaustive: (),
}
.into()
}

#[doc(hidden)]
pub fn alloc_error(layout: Layout) -> alloc::collections::TryReserveError {
#[cfg(feature = "use_unstable_apis")]
{
build_error_from_layout(layout)
}
#[cfg(not(feature = "use_unstable_apis"))]
{
internal::build_error_from_layout(layout)
}
}

#[test]
#[cfg(feature = "use_unstable_apis")]
fn check_error_transmute() {
let layout = core::alloc::Layout::new::<[i32; 42]>();
assert_eq!(
build_error_from_layout(layout),
internal::build_error_from_layout(layout)
);
}
Loading

0 comments on commit a99eacc

Please sign in to comment.