Skip to content
This repository was archived by the owner on Sep 11, 2023. It is now read-only.

Commit 4082f9f

Browse files
committed
Use Generic Associated Types for Enum trait
1 parent 2ffb519 commit 4082f9f

File tree

12 files changed

+108
-139
lines changed

12 files changed

+108
-139
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
strategy:
1515
matrix:
1616
toolchain:
17-
- 1.61
17+
- "1.65"
1818
- stable
1919
- beta
2020
- nightly

enum-map-derive/src/derive_enum.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl EnumGenerator {
3737
quote! {
3838
#[automatically_derived]
3939
impl ::enum_map::Enum for #name {
40-
const LENGTH: ::enum_map::usize = #length;
40+
type Array<V> = [V; #length];
4141

4242
#[inline]
4343
fn from_usize(value: ::enum_map::usize) -> Self {
@@ -53,11 +53,6 @@ impl EnumGenerator {
5353
}
5454
}
5555
}
56-
57-
#[automatically_derived]
58-
impl<V> ::enum_map::EnumArray<V> for #name {
59-
type Array = [V; #length];
60-
}
6156
}
6257
}
6358

enum-map-derive/src/derive_struct.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ impl StructGenerator {
102102
quote! {
103103
#[automatically_derived]
104104
impl ::enum_map::Enum for #name {
105-
const LENGTH: ::enum_map::usize = #length;
105+
type Array<V> = [V; #length];
106106

107107
#[inline]
108108
fn from_usize(value: ::enum_map::usize) -> Self {
@@ -114,11 +114,6 @@ impl StructGenerator {
114114
#into_usize
115115
}
116116
}
117-
118-
#[automatically_derived]
119-
impl<V> ::enum_map::EnumArray<V> for #name {
120-
type Array = [V; #length];
121-
}
122117
}
123118
}
124119
}

enum-map-derive/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,6 @@ pub fn derive_enum_map(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
165165

166166
fn type_length(ty: &Type) -> TokenStream {
167167
quote! {
168-
<#ty as ::enum_map::Enum>::LENGTH
168+
::enum_map::enum_len::<#ty>()
169169
}
170170
}

enum-map/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "enum-map"
33
version = "2.5.0"
44
authors = ["Konrad Borowski <[email protected]>"]
55
edition = "2021"
6-
rust-version = "1.61"
6+
rust-version = "1.65"
77
repository = "https://github.com/xfix/enum-map"
88
license = "MIT OR Apache-2.0"
99
description = "A map with C-like enum keys represented internally as an array"

enum-map/src/arbitrary.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1-
use crate::{enum_map, EnumArray, EnumMap};
1+
use crate::internal::Array;
2+
use crate::{enum_map, Enum, EnumMap};
23
use arbitrary::{Arbitrary, Result, Unstructured};
34

45
/// Requires crate feature `"arbitrary"`
5-
impl<'a, K: EnumArray<V>, V: Arbitrary<'a>> Arbitrary<'a> for EnumMap<K, V> {
6+
impl<'a, K: Enum, V: Arbitrary<'a>> Arbitrary<'a> for EnumMap<K, V> {
67
fn arbitrary(u: &mut Unstructured<'a>) -> Result<EnumMap<K, V>> {
78
Ok(enum_map! {
89
_ => Arbitrary::arbitrary(u)?,
910
})
1011
}
1112

1213
fn size_hint(depth: usize) -> (usize, Option<usize>) {
13-
if K::LENGTH == 0 {
14+
let len = K::Array::<V>::LENGTH;
15+
if len == 0 {
1416
(0, Some(0))
1517
} else {
1618
let (lo, hi) = V::size_hint(depth);
1719
(
18-
lo.saturating_mul(K::LENGTH),
19-
hi.and_then(|hi| hi.checked_mul(K::LENGTH)),
20+
lo.saturating_mul(len),
21+
hi.and_then(|hi| hi.checked_mul(len)),
2022
)
2123
}
2224
}

enum-map/src/enum_map_impls.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
use crate::{enum_map, EnumArray, EnumMap};
1+
use crate::{enum_map, Enum, EnumMap};
22
use core::fmt::{self, Debug, Formatter};
33
use core::hash::{Hash, Hasher};
44
use core::iter::{Extend, FromIterator};
55
use core::ops::{Index, IndexMut};
66

7-
impl<K: EnumArray<V> + Debug, V: Debug> Debug for EnumMap<K, V> {
7+
impl<K: Enum + Debug, V: Debug> Debug for EnumMap<K, V> {
88
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
99
f.debug_map().entries(self).finish()
1010
}
1111
}
1212

13-
impl<K: EnumArray<V>, V> Extend<(K, V)> for EnumMap<K, V> {
13+
impl<K: Enum, V> Extend<(K, V)> for EnumMap<K, V> {
1414
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
1515
for (key, value) in iter {
1616
self[key] = value;
@@ -20,7 +20,7 @@ impl<K: EnumArray<V>, V> Extend<(K, V)> for EnumMap<K, V> {
2020

2121
impl<'a, K, V> Extend<(&'a K, &'a V)> for EnumMap<K, V>
2222
where
23-
K: EnumArray<V> + Copy,
23+
K: Enum + Copy,
2424
V: Copy,
2525
{
2626
fn extend<I: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: I) {
@@ -31,7 +31,7 @@ where
3131
impl<K, V> FromIterator<(K, V)> for EnumMap<K, V>
3232
where
3333
Self: Default,
34-
K: EnumArray<V>,
34+
K: Enum,
3535
{
3636
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
3737
let mut map = EnumMap::default();
@@ -40,7 +40,7 @@ where
4040
}
4141
}
4242

43-
impl<K: EnumArray<V>, V> Index<K> for EnumMap<K, V> {
43+
impl<K: Enum, V> Index<K> for EnumMap<K, V> {
4444
type Output = V;
4545

4646
#[inline]
@@ -49,7 +49,7 @@ impl<K: EnumArray<V>, V> Index<K> for EnumMap<K, V> {
4949
}
5050
}
5151

52-
impl<K: EnumArray<V>, V> IndexMut<K> for EnumMap<K, V> {
52+
impl<K: Enum, V> IndexMut<K> for EnumMap<K, V> {
5353
#[inline]
5454
fn index_mut(&mut self, key: K) -> &mut V {
5555
&mut self.as_mut_slice()[key.into_usize()]
@@ -58,9 +58,9 @@ impl<K: EnumArray<V>, V> IndexMut<K> for EnumMap<K, V> {
5858

5959
// Implementations provided by derive attribute are too specific, and put requirements on K.
6060
// This is caused by rust-lang/rust#26925.
61-
impl<K: EnumArray<V>, V> Clone for EnumMap<K, V>
61+
impl<K: Enum, V> Clone for EnumMap<K, V>
6262
where
63-
K::Array: Clone,
63+
K::Array<V>: Clone,
6464
{
6565
#[inline]
6666
fn clone(&self) -> Self {
@@ -70,38 +70,38 @@ where
7070
}
7171
}
7272

73-
impl<K: EnumArray<V>, V> Copy for EnumMap<K, V> where K::Array: Copy {}
73+
impl<K: Enum, V> Copy for EnumMap<K, V> where K::Array<V>: Copy {}
7474

75-
impl<K: EnumArray<V>, V: PartialEq> PartialEq for EnumMap<K, V> {
75+
impl<K: Enum, V: PartialEq> PartialEq for EnumMap<K, V> {
7676
#[inline]
7777
fn eq(&self, other: &Self) -> bool {
7878
self.as_slice() == other.as_slice()
7979
}
8080
}
8181

82-
impl<K: EnumArray<V>, V: Eq> Eq for EnumMap<K, V> {}
82+
impl<K: Enum, V: Eq> Eq for EnumMap<K, V> {}
8383

84-
impl<K: EnumArray<V>, V: Hash> Hash for EnumMap<K, V> {
84+
impl<K: Enum, V: Hash> Hash for EnumMap<K, V> {
8585
#[inline]
8686
fn hash<H: Hasher>(&self, state: &mut H) {
8787
self.as_slice().hash(state);
8888
}
8989
}
9090

91-
impl<K: EnumArray<V>, V: Default> Default for EnumMap<K, V> {
91+
impl<K: Enum, V: Default> Default for EnumMap<K, V> {
9292
#[inline]
9393
fn default() -> Self {
9494
enum_map! { _ => V::default() }
9595
}
9696
}
9797

98-
impl<K: EnumArray<V>, V: PartialOrd> PartialOrd for EnumMap<K, V> {
98+
impl<K: Enum, V: PartialOrd> PartialOrd for EnumMap<K, V> {
9999
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
100100
self.as_slice().partial_cmp(other.as_slice())
101101
}
102102
}
103103

104-
impl<K: EnumArray<V>, V: Ord> Ord for EnumMap<K, V> {
104+
impl<K: Enum, V: Ord> Ord for EnumMap<K, V> {
105105
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
106106
self.as_slice().cmp(other.as_slice())
107107
}

enum-map/src/internal.rs

Lines changed: 15 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,44 +9,40 @@ use core::convert::Infallible;
99
/// strictly speaking not an actual enum, there are good reasons to consider
1010
/// it like one, as array of `u8` keys is a relatively common pattern.
1111
pub trait Enum: Sized {
12-
/// Length of the enum.
13-
const LENGTH: usize;
12+
/// Representation of an enum.
13+
///
14+
/// For an enum with four elements it looks like this.
15+
///
16+
/// ```
17+
/// type Array<V> = [V; 4];
18+
/// ```
19+
type Array<V>: Array;
1420

1521
/// Takes an usize, and returns an element matching `into_usize` function.
1622
fn from_usize(value: usize) -> Self;
1723
/// Returns an unique identifier for a value within range of `0..Array::LENGTH`.
1824
fn into_usize(self) -> usize;
1925
}
2026

21-
/// Trait associating enum with an array.
22-
///
23-
/// This exists due to limitations of Rust compiler that prevent arrays from using
24-
/// associated constants in structures. The array length must match `LENGTH` of an
25-
/// `Enum`.
26-
pub trait EnumArray<V>: Enum {
27-
/// Representation of an enum map for type `V`.
28-
type Array: Array<V>;
29-
}
30-
3127
/// Array for enum-map storage.
3228
///
3329
/// This trait is inteded for primitive array types (with fixed length).
3430
///
3531
/// # Safety
3632
///
3733
/// The array length needs to match actual storage.
38-
pub unsafe trait Array<V> {
34+
pub unsafe trait Array {
3935
// This is necessary duplication because the length in Enum trait can be
4036
// provided by user and may not be trustworthy for unsafe code.
4137
const LENGTH: usize;
4238
}
4339

44-
unsafe impl<V, const N: usize> Array<V> for [V; N] {
40+
unsafe impl<V, const N: usize> Array for [V; N] {
4541
const LENGTH: usize = N;
4642
}
4743

4844
impl Enum for bool {
49-
const LENGTH: usize = 2;
45+
type Array<V> = [V; 2];
5046

5147
#[inline]
5248
fn from_usize(value: usize) -> Self {
@@ -62,12 +58,8 @@ impl Enum for bool {
6258
}
6359
}
6460

65-
impl<T> EnumArray<T> for bool {
66-
type Array = [T; Self::LENGTH];
67-
}
68-
6961
impl Enum for () {
70-
const LENGTH: usize = 1;
62+
type Array<V> = [V; 1];
7163

7264
#[inline]
7365
fn from_usize(value: usize) -> Self {
@@ -82,12 +74,8 @@ impl Enum for () {
8274
}
8375
}
8476

85-
impl<T> EnumArray<T> for () {
86-
type Array = [T; Self::LENGTH];
87-
}
88-
8977
impl Enum for u8 {
90-
const LENGTH: usize = 256;
78+
type Array<V> = [V; 256];
9179

9280
#[inline]
9381
fn from_usize(value: usize) -> Self {
@@ -99,12 +87,8 @@ impl Enum for u8 {
9987
}
10088
}
10189

102-
impl<T> EnumArray<T> for u8 {
103-
type Array = [T; Self::LENGTH];
104-
}
105-
10690
impl Enum for Infallible {
107-
const LENGTH: usize = 0;
91+
type Array<V> = [V; 0];
10892

10993
#[inline]
11094
fn from_usize(_: usize) -> Self {
@@ -116,12 +100,8 @@ impl Enum for Infallible {
116100
}
117101
}
118102

119-
impl<T> EnumArray<T> for Infallible {
120-
type Array = [T; Self::LENGTH];
121-
}
122-
123103
impl Enum for Ordering {
124-
const LENGTH: usize = 3;
104+
type Array<V> = [V; 3];
125105

126106
#[inline]
127107
fn from_usize(value: usize) -> Self {
@@ -141,7 +121,3 @@ impl Enum for Ordering {
141121
}
142122
}
143123
}
144-
145-
impl<T> EnumArray<T> for Ordering {
146-
type Array = [T; Self::LENGTH];
147-
}

0 commit comments

Comments
 (0)