Skip to content

Commit 6e310f2

Browse files
committed
Auto merge of #62435 - scottmcm:constrained-array-impls, r=centril
Use const generics for array impls [part 1] Part 1 of #61415, following the plan in #61415 (comment) Found a way that works 🙃
2 parents 9210359 + d6a9793 commit 6e310f2

9 files changed

+479
-8
lines changed

src/libcore/array.rs

+320
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ impl From<Infallible> for TryFromSliceError {
8181
}
8282
}
8383

84+
#[cfg(bootstrap)]
8485
macro_rules! __impl_slice_eq1 {
8586
($Lhs: ty, $Rhs: ty) => {
8687
__impl_slice_eq1! { $Lhs, $Rhs, Sized }
@@ -96,6 +97,7 @@ macro_rules! __impl_slice_eq1 {
9697
}
9798
}
9899

100+
#[cfg(bootstrap)]
99101
macro_rules! __impl_slice_eq2 {
100102
($Lhs: ty, $Rhs: ty) => {
101103
__impl_slice_eq2! { $Lhs, $Rhs, Sized }
@@ -114,6 +116,7 @@ macro_rules! __impl_slice_eq2 {
114116
}
115117

116118
// macro for implementing n-element array functions and operations
119+
#[cfg(bootstrap)]
117120
macro_rules! array_impls {
118121
($($N:expr)+) => {
119122
$(
@@ -264,6 +267,323 @@ macro_rules! array_impls {
264267
}
265268
}
266269

270+
#[cfg(not(bootstrap))]
271+
mod impls_using_const_generics {
272+
use super::*;
273+
274+
#[stable(feature = "rust1", since = "1.0.0")]
275+
impl<T, const N: usize> AsRef<[T]> for [T; N]
276+
where
277+
[T; N]: LengthAtMost32,
278+
{
279+
#[inline]
280+
fn as_ref(&self) -> &[T] {
281+
&self[..]
282+
}
283+
}
284+
285+
#[stable(feature = "rust1", since = "1.0.0")]
286+
impl<T, const N: usize> AsMut<[T]> for [T; N]
287+
where
288+
[T; N]: LengthAtMost32,
289+
{
290+
#[inline]
291+
fn as_mut(&mut self) -> &mut [T] {
292+
&mut self[..]
293+
}
294+
}
295+
296+
#[stable(feature = "array_borrow", since = "1.4.0")]
297+
impl<T, const N: usize> Borrow<[T]> for [T; N]
298+
where
299+
[T; N]: LengthAtMost32,
300+
{
301+
fn borrow(&self) -> &[T] {
302+
self
303+
}
304+
}
305+
306+
#[stable(feature = "array_borrow", since = "1.4.0")]
307+
impl<T, const N: usize> BorrowMut<[T]> for [T; N]
308+
where
309+
[T; N]: LengthAtMost32,
310+
{
311+
fn borrow_mut(&mut self) -> &mut [T] {
312+
self
313+
}
314+
}
315+
316+
#[stable(feature = "try_from", since = "1.34.0")]
317+
impl<T, const N: usize> TryFrom<&[T]> for [T; N]
318+
where
319+
T: Copy,
320+
[T; N]: LengthAtMost32,
321+
{
322+
type Error = TryFromSliceError;
323+
324+
fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> {
325+
<&Self>::try_from(slice).map(|r| *r)
326+
}
327+
}
328+
329+
#[stable(feature = "try_from", since = "1.34.0")]
330+
impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N]
331+
where
332+
[T; N]: LengthAtMost32,
333+
{
334+
type Error = TryFromSliceError;
335+
336+
fn try_from(slice: &[T]) -> Result<&[T; N], TryFromSliceError> {
337+
if slice.len() == N {
338+
let ptr = slice.as_ptr() as *const [T; N];
339+
unsafe { Ok(&*ptr) }
340+
} else {
341+
Err(TryFromSliceError(()))
342+
}
343+
}
344+
}
345+
346+
#[stable(feature = "try_from", since = "1.34.0")]
347+
impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N]
348+
where
349+
[T; N]: LengthAtMost32,
350+
{
351+
type Error = TryFromSliceError;
352+
353+
fn try_from(slice: &mut [T]) -> Result<&mut [T; N], TryFromSliceError> {
354+
if slice.len() == N {
355+
let ptr = slice.as_mut_ptr() as *mut [T; N];
356+
unsafe { Ok(&mut *ptr) }
357+
} else {
358+
Err(TryFromSliceError(()))
359+
}
360+
}
361+
}
362+
363+
#[stable(feature = "rust1", since = "1.0.0")]
364+
impl<T: Hash, const N: usize> Hash for [T; N]
365+
where
366+
[T; N]: LengthAtMost32,
367+
{
368+
fn hash<H: hash::Hasher>(&self, state: &mut H) {
369+
Hash::hash(&self[..], state)
370+
}
371+
}
372+
373+
#[stable(feature = "rust1", since = "1.0.0")]
374+
impl<T: fmt::Debug, const N: usize> fmt::Debug for [T; N]
375+
where
376+
[T; N]: LengthAtMost32,
377+
{
378+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
379+
fmt::Debug::fmt(&&self[..], f)
380+
}
381+
}
382+
383+
#[stable(feature = "rust1", since = "1.0.0")]
384+
impl<'a, T, const N: usize> IntoIterator for &'a [T; N]
385+
where
386+
[T; N]: LengthAtMost32,
387+
{
388+
type Item = &'a T;
389+
type IntoIter = Iter<'a, T>;
390+
391+
fn into_iter(self) -> Iter<'a, T> {
392+
self.iter()
393+
}
394+
}
395+
396+
#[stable(feature = "rust1", since = "1.0.0")]
397+
impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N]
398+
where
399+
[T; N]: LengthAtMost32,
400+
{
401+
type Item = &'a mut T;
402+
type IntoIter = IterMut<'a, T>;
403+
404+
fn into_iter(self) -> IterMut<'a, T> {
405+
self.iter_mut()
406+
}
407+
}
408+
409+
#[stable(feature = "rust1", since = "1.0.0")]
410+
impl<'a, 'b, A, B, const N: usize> PartialEq<[B; N]> for [A; N]
411+
where
412+
A: PartialEq<B>,
413+
[A; N]: LengthAtMost32,
414+
[B; N]: LengthAtMost32,
415+
{
416+
#[inline]
417+
fn eq(&self, other: &[B; N]) -> bool {
418+
self[..] == other[..]
419+
}
420+
#[inline]
421+
fn ne(&self, other: &[B; N]) -> bool {
422+
self[..] != other[..]
423+
}
424+
}
425+
426+
#[stable(feature = "rust1", since = "1.0.0")]
427+
impl<'a, 'b, A, B, const N: usize> PartialEq<[B]> for [A; N]
428+
where
429+
A: PartialEq<B>,
430+
[A; N]: LengthAtMost32,
431+
{
432+
#[inline]
433+
fn eq(&self, other: &[B]) -> bool {
434+
self[..] == other[..]
435+
}
436+
#[inline]
437+
fn ne(&self, other: &[B]) -> bool {
438+
self[..] != other[..]
439+
}
440+
}
441+
442+
#[stable(feature = "rust1", since = "1.0.0")]
443+
impl<'a, 'b, A, B, const N: usize> PartialEq<[A; N]> for [B]
444+
where
445+
B: PartialEq<A>,
446+
[A; N]: LengthAtMost32,
447+
{
448+
#[inline]
449+
fn eq(&self, other: &[A; N]) -> bool {
450+
self[..] == other[..]
451+
}
452+
#[inline]
453+
fn ne(&self, other: &[A; N]) -> bool {
454+
self[..] != other[..]
455+
}
456+
}
457+
458+
#[stable(feature = "rust1", since = "1.0.0")]
459+
impl<'a, 'b, A, B, const N: usize> PartialEq<&'b [B]> for [A; N]
460+
where
461+
A: PartialEq<B>,
462+
[A; N]: LengthAtMost32,
463+
{
464+
#[inline]
465+
fn eq(&self, other: &&'b [B]) -> bool {
466+
self[..] == other[..]
467+
}
468+
#[inline]
469+
fn ne(&self, other: &&'b [B]) -> bool {
470+
self[..] != other[..]
471+
}
472+
}
473+
474+
#[stable(feature = "rust1", since = "1.0.0")]
475+
impl<'a, 'b, A, B, const N: usize> PartialEq<[A; N]> for &'b [B]
476+
where
477+
B: PartialEq<A>,
478+
[A; N]: LengthAtMost32,
479+
{
480+
#[inline]
481+
fn eq(&self, other: &[A; N]) -> bool {
482+
self[..] == other[..]
483+
}
484+
#[inline]
485+
fn ne(&self, other: &[A; N]) -> bool {
486+
self[..] != other[..]
487+
}
488+
}
489+
490+
#[stable(feature = "rust1", since = "1.0.0")]
491+
impl<'a, 'b, A, B, const N: usize> PartialEq<&'b mut [B]> for [A; N]
492+
where
493+
A: PartialEq<B>,
494+
[A; N]: LengthAtMost32,
495+
{
496+
#[inline]
497+
fn eq(&self, other: &&'b mut [B]) -> bool {
498+
self[..] == other[..]
499+
}
500+
#[inline]
501+
fn ne(&self, other: &&'b mut [B]) -> bool {
502+
self[..] != other[..]
503+
}
504+
}
505+
506+
#[stable(feature = "rust1", since = "1.0.0")]
507+
impl<'a, 'b, A, B, const N: usize> PartialEq<[A; N]> for &'b mut [B]
508+
where
509+
B: PartialEq<A>,
510+
[A; N]: LengthAtMost32,
511+
{
512+
#[inline]
513+
fn eq(&self, other: &[A; N]) -> bool {
514+
self[..] == other[..]
515+
}
516+
#[inline]
517+
fn ne(&self, other: &[A; N]) -> bool {
518+
self[..] != other[..]
519+
}
520+
}
521+
522+
// NOTE: some less important impls are omitted to reduce code bloat
523+
// __impl_slice_eq2! { [A; $N], &'b [B; $N] }
524+
// __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }
525+
526+
#[stable(feature = "rust1", since = "1.0.0")]
527+
impl<T: Eq, const N: usize> Eq for [T; N] where [T; N]: LengthAtMost32 {}
528+
529+
#[stable(feature = "rust1", since = "1.0.0")]
530+
impl<T: PartialOrd, const N: usize> PartialOrd for [T; N]
531+
where
532+
[T; N]: LengthAtMost32,
533+
{
534+
#[inline]
535+
fn partial_cmp(&self, other: &[T; N]) -> Option<Ordering> {
536+
PartialOrd::partial_cmp(&&self[..], &&other[..])
537+
}
538+
#[inline]
539+
fn lt(&self, other: &[T; N]) -> bool {
540+
PartialOrd::lt(&&self[..], &&other[..])
541+
}
542+
#[inline]
543+
fn le(&self, other: &[T; N]) -> bool {
544+
PartialOrd::le(&&self[..], &&other[..])
545+
}
546+
#[inline]
547+
fn ge(&self, other: &[T; N]) -> bool {
548+
PartialOrd::ge(&&self[..], &&other[..])
549+
}
550+
#[inline]
551+
fn gt(&self, other: &[T; N]) -> bool {
552+
PartialOrd::gt(&&self[..], &&other[..])
553+
}
554+
}
555+
556+
#[stable(feature = "rust1", since = "1.0.0")]
557+
impl<T: Ord, const N: usize> Ord for [T; N]
558+
where
559+
[T; N]: LengthAtMost32,
560+
{
561+
#[inline]
562+
fn cmp(&self, other: &[T; N]) -> Ordering {
563+
Ord::cmp(&&self[..], &&other[..])
564+
}
565+
}
566+
}
567+
568+
/// Implemented for lengths where trait impls are allowed on arrays in core/std
569+
#[rustc_on_unimplemented(
570+
message="arrays only have std trait implementations for lengths 0..=32",
571+
)]
572+
#[unstable(feature = "const_generic_impls_guard", issue = "0",
573+
reason = "will never be stable, just a temporary step until const generics are stable")]
574+
#[cfg(not(bootstrap))]
575+
pub trait LengthAtMost32 {}
576+
577+
#[cfg(not(bootstrap))]
578+
macro_rules! array_impls {
579+
($($N:literal)+) => {
580+
$(
581+
#[unstable(feature = "const_generic_impls_guard", issue = "0")]
582+
impl<T> LengthAtMost32 for [T; $N] {}
583+
)+
584+
}
585+
}
586+
267587
array_impls! {
268588
0 1 2 3 4 5 6 7 8 9
269589
10 11 12 13 14 15 16 17 18 19

src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
#![feature(concat_idents)]
7575
#![feature(const_fn)]
7676
#![feature(const_fn_union)]
77+
#![cfg_attr(not(bootstrap), feature(const_generics))]
7778
#![feature(custom_inner_attributes)]
7879
#![feature(decl_macro)]
7980
#![feature(doc_cfg)]

0 commit comments

Comments
 (0)