Skip to content

Commit a99eacc

Browse files
authored
Enable crate to be used with the stable compiler (#10)
1 parent 784001f commit a99eacc

File tree

9 files changed

+462
-263
lines changed

9 files changed

+462
-263
lines changed

.github/workflows/build-and-test.yml

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,39 +26,17 @@ jobs:
2626
target: x86_64-unknown-linux-gnu
2727
runs-on: ${{ matrix.os }}
2828
env:
29-
RUSTC_BOOTSTRAP: 1
3029
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
3130
steps:
3231
- name: Checkout
3332
uses: actions/checkout@v3
3433

35-
- name: Run tests
36-
run: cargo test --locked
37-
38-
- name: Clippy
39-
run: cargo clippy --locked -- -D warnings
40-
41-
- name: Check formatting
42-
run: cargo fmt --check
43-
44-
- name: Check docs
45-
run: cargo doc --locked
46-
env:
47-
RUSTDOCFLAGS: -D warnings
34+
- name: Update Rust toolchain
35+
run: rustup update
4836

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

52-
- name: Build with no_global_oom_handling
53-
run: cargo build --locked -Z build-std=core,alloc --target ${{ matrix.target }} -Z sparse-registry
54-
env:
55-
RUSTFLAGS: --cfg no_global_oom_handling
56-
57-
- name: Install miri
58-
run: rustup toolchain install nightly --component miri
59-
60-
- name: Setup miri
61-
run: cargo +nightly miri setup
62-
63-
- name: Run tests under miri
64-
run: cargo +nightly miri test
40+
- name: Run build script
41+
shell: pwsh
42+
run: .\build.ps1 -BuildLocked

Cargo.lock

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
[package]
22
name = "fallible_vec"
33
description = "Fallible allocation functions for the Rust standard library's `Vec` type."
4-
version = "0.2.0"
4+
version = "0.3.0"
55
edition = "2021"
66
license-file = "LICENSE"
77
repository = "https://github.com/microsoft/rust_fallible_vec"
88
readme = "README.md"
99
categories = ["embedded", "memory-management", "no-std"]
1010
keywords = ["vec", "fallible", "collections", "no_std"]
11+
12+
[dependencies]
13+
static_assertions = "1.1"
14+
15+
[features]
16+
default = ["allocator_api", "use_unstable_apis"]
17+
allocator_api = []
18+
use_unstable_apis = []

README.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ Fallible allocation functions for the Rust standard library's [`alloc::vec::Vec`
55
These functions are designed to be usable with `#![no_std]`, `#[cfg(no_global_oom_handling)]` (see
66
<https://github.com/rust-lang/rust/pull/84266>) enabled and Allocators (see <https://github.com/rust-lang/wg-allocators>).
77

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

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

93+
## Building locally
94+
95+
The recommended way to build locally is to use the `build.ps1` script: this will build the crate
96+
using all feature combinations, run tests, check formatting, run clippy and build with `#[cfg(no_global_oom_handling)]`
97+
enabled.
98+
99+
In order to run this script you'll need:
100+
* [PowerShell 7+](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell)
101+
* [Rust](https://rustup.rs/)
102+
* Including the [`rust-src` component](https://rust-lang.github.io/rustup/concepts/components.html).
103+
89104
## Contributing
90105

91106
This project welcomes contributions and suggestions. Most contributions require you to agree to a

build.ps1

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,29 @@
1+
#Requires -Version 7
2+
3+
<#
4+
.SYNOPSIS
5+
Builds the `fallible_vec` crate, runs tests, checks formatting, runs clippy.
6+
7+
.PARAMETER BuildLocked
8+
Adds `--locked` to the build commands to prevent the `Cargo.lock` file from being updated. This is
9+
useful for CI builds.
10+
11+
.NOTES
12+
See README.md for details on the environment that this script expects.
13+
#>
14+
param (
15+
[Parameter(Mandatory = $false)]
16+
[switch]
17+
$BuildLocked
18+
)
19+
120
Set-StrictMode -Version Latest
221
$ErrorActionPreference = 'Stop'
322

4-
function Invoke-CheckExitCode([scriptblock]$ScriptBlock) {
23+
$lockedArg = $BuildLocked ? '--locked' : $null
24+
25+
function Invoke-CheckExitCode([string] $Description, [scriptblock]$ScriptBlock) {
26+
Write-Host "==== $Description ===="
527
& $ScriptBlock
628
if ($LASTEXITCODE -ne 0) {
729
exit $LASTEXITCODE
@@ -31,23 +53,32 @@ Invoke-WithEnvironment `
3153
'env:RUSTC_BOOTSTRAP' = '1';
3254
# Fail 'cargo doc' on warnings.
3355
'env:RUSTDOCFLAGS' = '-D warnings';
56+
# Fail 'cargo build' on warnings.
57+
'env:RUSTFLAGS' = '-D warnings';
3458
} `
3559
-ScriptBlock {
60+
#
61+
# Check that enabling various feature combinations works.
62+
#
63+
Invoke-CheckExitCode 'Build default' { cargo build $lockedArg }
64+
Invoke-CheckExitCode 'Build allocator_api only' { cargo build $lockedArg --no-default-features --features allocator_api }
65+
Invoke-CheckExitCode 'Build use_unstable_apis only' { cargo build $lockedArg --no-default-features --features use_unstable_apis }
66+
3667
#
3768
# Run tests
3869
#
39-
Invoke-CheckExitCode { cargo test --locked }
70+
Invoke-CheckExitCode 'Test' { cargo test --locked }
4071

4172
#
4273
# Lint and check formatting.
4374
#
44-
Invoke-CheckExitCode { cargo clippy --locked -- -D warnings }
45-
Invoke-CheckExitCode { cargo fmt --check }
75+
Invoke-CheckExitCode 'Clippy' { cargo clippy --locked -- -D warnings }
76+
Invoke-CheckExitCode 'Check format' { cargo fmt --check }
4677

4778
#
4879
# Check docs
4980
#
50-
Invoke-CheckExitCode { cargo doc --locked }
81+
Invoke-CheckExitCode 'Check docs' { cargo doc --locked }
5182

5283
#
5384
# Verify that we can build with #[cfg(no_global_oom_handling)] enabled.
@@ -71,11 +102,14 @@ Invoke-WithEnvironment `
71102
'env:RUSTFLAGS' = '--cfg no_global_oom_handling';
72103
} `
73104
-ScriptBlock {
74-
Invoke-CheckExitCode { cargo build --locked -Z build-std=core,alloc --target $target }
105+
Invoke-CheckExitCode 'Build no_global_oom_handling' { cargo build $lockedArg -Z build-std=core,alloc --target $target }
75106
}
76107
}
77108

109+
# Build with no features enabled (should work on the non-nightly compiler).
110+
Invoke-CheckExitCode 'Build no features' { cargo build $lockedArg --no-default-features }
111+
78112
# Run tests under miri
79-
Invoke-CheckExitCode { rustup toolchain install nightly --component miri }
80-
Invoke-CheckExitCode { cargo +nightly miri setup }
81-
Invoke-CheckExitCode { cargo +nightly miri test }
113+
Invoke-CheckExitCode 'Install miri' { rustup toolchain install nightly --component miri }
114+
Invoke-CheckExitCode 'Setup miti' { cargo +nightly miri setup }
115+
Invoke-CheckExitCode 'Miri test' { cargo +nightly miri test }

src/collect.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use crate::FallibleVec;
2-
use alloc::{collections::TryReserveError, vec::Vec};
2+
use crate::TryReserveError;
3+
use alloc::vec::Vec;
4+
5+
#[cfg(feature = "allocator_api")]
36
use core::alloc::Allocator;
47

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

2529
/// Attempts to collect items from an iterator into a vector.
@@ -43,6 +47,7 @@ impl<T, I> TryCollect<T> for I
4347
where
4448
I: IntoIterator<Item = T>,
4549
{
50+
#[cfg(feature = "allocator_api")]
4651
fn try_collect_in<A: Allocator>(self, alloc: A) -> Result<Vec<T, A>, TryReserveError> {
4752
let mut vec = Vec::new_in(alloc);
4853
vec.try_extend(self.into_iter())?;

src/error.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use core::alloc::Layout;
2+
3+
#[allow(dead_code)]
4+
#[cfg(any(test, not(feature = "use_unstable_apis")))]
5+
mod internal {
6+
// Forked from the Rust Standard Library: library/alloc/src/collections/mod.rs
7+
use super::*;
8+
9+
/// The error type for `try_reserve` methods.
10+
pub struct TryReserveError {
11+
pub kind: TryReserveErrorKind,
12+
}
13+
14+
/// Details of the allocation that caused a `TryReserveError`
15+
pub enum TryReserveErrorKind {
16+
/// Error due to the computed capacity exceeding the collection's maximum
17+
/// (usually `isize::MAX` bytes).
18+
CapacityOverflow,
19+
20+
/// The memory allocator returned an error
21+
AllocError {
22+
/// The layout of allocation request that failed
23+
layout: Layout,
24+
non_exhaustive: (),
25+
},
26+
}
27+
28+
pub fn build_error_from_layout(layout: Layout) -> alloc::collections::TryReserveError {
29+
static_assertions::assert_eq_size!(
30+
alloc::collections::TryReserveError,
31+
internal::TryReserveError
32+
);
33+
unsafe {
34+
core::mem::transmute(internal::TryReserveError {
35+
kind: internal::TryReserveErrorKind::AllocError {
36+
layout,
37+
non_exhaustive: (),
38+
},
39+
})
40+
}
41+
}
42+
}
43+
44+
#[cfg(feature = "use_unstable_apis")]
45+
fn build_error_from_layout(layout: Layout) -> alloc::collections::TryReserveError {
46+
alloc::collections::TryReserveErrorKind::AllocError {
47+
layout,
48+
non_exhaustive: (),
49+
}
50+
.into()
51+
}
52+
53+
#[doc(hidden)]
54+
pub fn alloc_error(layout: Layout) -> alloc::collections::TryReserveError {
55+
#[cfg(feature = "use_unstable_apis")]
56+
{
57+
build_error_from_layout(layout)
58+
}
59+
#[cfg(not(feature = "use_unstable_apis"))]
60+
{
61+
internal::build_error_from_layout(layout)
62+
}
63+
}
64+
65+
#[test]
66+
#[cfg(feature = "use_unstable_apis")]
67+
fn check_error_transmute() {
68+
let layout = core::alloc::Layout::new::<[i32; 42]>();
69+
assert_eq!(
70+
build_error_from_layout(layout),
71+
internal::build_error_from_layout(layout)
72+
);
73+
}

0 commit comments

Comments
 (0)