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

0.3.8 release #25

Merged
merged 7 commits into from
Dec 6, 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
12 changes: 12 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@ This is the changelog, summarising changes in each version(some minor changes ma

# 0.3

### 0.3.8

Removed most `Copy` restriction of these macros:
- `konst::array::from_fn`
- `konst::array::map`
- `konst::iter::collect_const`
The pattern of the closure passed to `konst::array::map` is still required not to move out of the input array.

Improved `konst::array::{from_fn, map}` macros by allowing its closure parameter to take more unparenthesized patterns.

Improved the `konst::iter::{collect_const, eval, for_each}` macros by allowing single-parameter closures passed to the macro to annotate the type of the parameter.

### 0.3.7

Fixed `ChunksExact::remainder`'s implementation, it used to return the entire uniterated-over slice, when it should only return the part of the slice that the iterator never yields.
Expand Down
4 changes: 2 additions & 2 deletions konst/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "konst"
version = "0.3.7"
version = "0.3.8"
authors = ["rodrimati1992 <[email protected]>"]
rust-version = "1.65.0"
edition = "2021"
Expand All @@ -25,7 +25,7 @@ path = "../konst_proc_macros"
optional = true

[dependencies.konst_kernel]
version = "=0.3.6"
version = "=0.3.8"
path = "../konst_kernel"
features = ["rust_1_64", "__for_konst"]

Expand Down
60 changes: 56 additions & 4 deletions konst/src/array.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,37 @@
//! Const equivalents of array functions.

macro_rules! leak_warning {
() => {
concat!(
"# Warning\n",
"\n",
"This macro leaks the initialized part of the array\n",
"if the closure passed to this macro panics or returns early.\n",
"\n",
"note: this warning is not relevant if the elements don't need dropping",
"(e.g: by implementing `Copy`).\n"
)
};
}

/// Const equivalent of
/// [`array::map`](https://doc.rust-lang.org/std/primitive.array.html#method.map).
///
/// **Limitation:** requires `$array` and the elements
/// returned by the passed-in function to be `Copy`.
#[doc = leak_warning!()]
///
/// # Limitations
///
/// This macro supports mapping from non-Copy arrays if any of these
/// conditions are met about the parameter of the passed-in closure:
/// 1. it's a pattern that only copies Copy fields of each array element
/// 2. it's a `ref` pattern
///
/// [examples of both of the above conditions below](#map-noncopy-example)
///
/// # Example
///
/// ### Basic
///
/// ```rust
/// use konst::array;
///
Expand All @@ -28,13 +52,41 @@
///
/// ```
///
/// <span id="map-noncopy-example"> </span>
/// ### Map from non-Copy array
///
/// Demonstrates both ways to map from a non-Copy array.
///
/// ```rust
/// use konst::array;
///
/// struct NonCopy(u32, u32);
///
/// const PRIME_SUMS: [u32; 3] = {
/// let input = [NonCopy(2, 3), NonCopy(5, 7), NonCopy(11, 13)];
///
/// // demonstrates the first way to map from non-Copy elements
/// array::map!(input, |NonCopy(l, r)| l + r)
/// };
/// assert_eq!(PRIME_SUMS, [5, 12, 24]);
///
/// const FIBB_SUMS: [u32; 3] = {
/// let input = [NonCopy(2, 3), NonCopy(5, 8), NonCopy(13, 21)];
///
/// // demonstrates the second way to map from non-Copy elements
/// array::map!(input, |ref nc| nc.0 + nc.1)
/// };
/// assert_eq!(FIBB_SUMS, [5, 13, 34]);
///
/// ```
///
pub use konst_kernel::array_map as map;

/// Const equivalent of [`array::from_fn`](core::array::from_fn).
///
/// # Limitations
#[doc = leak_warning!()]
///
/// This macro requires the element type to be `Copy`.
/// # Limitations
///
/// When the array type is annotated, the array type must be one of:
/// - Square brackets (e.g: `from_fn!([usize; 10] => |i| i)`)
Expand Down
121 changes: 93 additions & 28 deletions konst/tests/misc_tests/array_tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
use crate::misc_tests::test_utils::assert_type;

use konst::array;

#[derive(Debug, PartialEq)]
struct NonCopy<T>(T);

#[test]
#[should_panic]
#[allow(unreachable_code)]
Expand All @@ -8,46 +13,98 @@ fn array_map_break() {
}

#[test]
fn array_map_basic_test() {
use konst::array::map;
fn array_map_non_copy() {
const fn map_foos<const N: usize>(input: [NonCopy<u8>; N]) -> [NonCopy<i8>; N] {
array::map!(input, |NonCopy(x)| NonCopy(x as i8))
}

{
// ensuring that `return` returns from the enclosing named function.
const fn map_evens<const N: usize>(input: [u8; N]) -> Option<[u8; N]> {
Some(map!(input, |x| if x % 2 == 0 {
x * 2
} else {
return None;
}))
}
assert_eq!(
map_foos([0, 1, 255u8].map(NonCopy)),
[0, 1, -1i8].map(NonCopy)
);
}

assert_eq!(map_evens([2, 4, 6]), Some([4, 8, 12]));
assert_eq!(map_evens([2, 3, 6]), None);
#[test]
fn array_map_non_copy_ref_pat() {
const fn map_foos<const N: usize>(input: [NonCopy<u8>; N]) -> [NonCopy<i8>; N] {
array::map!(input, |ref x| NonCopy(x.0 as i8))
}
{
// ensuring that the type annotation is used
const SQUARED: [u32; 3] = map!([3, 5, 8], |x: u32| x.pow(2));

assert_eq!(SQUARED, [9, 25, 64]);
assert_eq!(
map_foos([0, 1, 255u8].map(NonCopy)),
[0, 1, -1i8].map(NonCopy)
);
}

#[test]
fn array_map_nonlocal_return() {
const fn map_evens<const N: usize>(input: [u8; N]) -> Option<[u8; N]> {
Some(array::map!(input, |x| if x % 2 == 0 {
x * 2
} else {
return None;
}))
}
{
// ensuring that functions can be used
const X: [Option<u32>; 2] = map!([10, 20], Some);
const Y: [u32; 3] = map!([0b1, 0b11, 0b111], <u32>::count_ones);

assert_eq!(X, [Some(10), Some(20)]);
assert_eq!(Y, [1, 2, 3]);
assert_eq!(map_evens([2, 4, 6]), Some([4, 8, 12]));
assert_eq!(map_evens([2, 3, 6]), None);
}

#[test]
fn array_map_type_annotation() {
macro_rules! with_comma {
(($($p:tt)*) ($($e:tt)*)) => ({
// ensuring that the type annotation is used
const SQUARED: [u32; 3] =
array::map!([3, 5, 8], |x: u32 $($p)*| x.pow(2) $($e)*);

assert_eq!(SQUARED, [9, 25, 64]);
})
}

with_comma! {() ()}
with_comma! {(,) ()}
with_comma! {() (,)}
with_comma! {(,) (,)}
}

#[test]
fn array_map_pattern_param() {
struct Foo(u32, u32);

macro_rules! with_comma {
(($($p:tt)*) ($($e:tt)*)) => ({
// ensuring that the type annotation is used
const FIBB: [u32; 3] = array::map!(
[Foo(3, 5), Foo(8, 13), Foo(21, 34)],
|Foo(l, r) $($p)*| l + r $($e)*
);

assert_eq!(FIBB, [8, 21, 55]);
})
}

with_comma! {() ()}
with_comma! {(,) ()}
with_comma! {() (,)}
with_comma! {(,) (,)}
}

#[test]
fn array_map_more_tests() {
fn array_map_pass_function_as_arg() {
const X: [Option<u32>; 2] = array::map!([10, 20], Some);
const Y: [u32; 3] = array::map!([0b1, 0b11, 0b111], <u32>::count_ones);

assert_eq!(X, [Some(10), Some(20)]);
assert_eq!(Y, [1, 2, 3]);
}

#[test]
fn array_map_with_type_annotation() {
use konst::array::map;

{
let mapped = map!([(); 3], |_| -> u32 { Default::default() });
assert_type::<_, [u32; 3]>(&mapped);
}
let mapped = map!([(); 3], |_| -> u32 { Default::default() });
assert_type::<_, [u32; 3]>(&mapped);
}

#[test]
Expand Down Expand Up @@ -124,6 +181,14 @@ fn array_from_fn_tests() {
}
}

#[test]
fn array_from_fn_non_copy() {
assert_eq!(
konst::array::from_fn!([NonCopy<usize>; 3] => NonCopy),
[0usize, 1, 2].map(NonCopy),
);
}

#[test]
#[should_panic]
#[allow(unreachable_code)]
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading