Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable crate to be used with the stable compiler #10

Merged
merged 1 commit into from
Mar 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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