Higher-ranked trait bounds with constants, variadic generics, heterogeneous iteration, tuple indexing

Let's say one wants to implement traits for "typed" regular expressions with capture groups:

trait RegexWithMatchGroups
    Self: for <const N: usize in 0..Self::MATCH_GROUPS> HasMatchGroup<N>
{
    fn re() -> &'static Regex;
    const MATCH_GROUPS: usize;
}

trait HasMatchGroup<const N: usize>
where
    // For N=0, the range is empty, so this trait is not implemented
    Self: for <const M: usize in 0..N)> HasMatchGroup<M>,
{
    // Sized by default
    type Output;
}

That's the kind of syntax and semantics that I would like to see.

Interestingly enough, there's a pattern that can act as a variadic generic (see template parameter packs in C++). Because T::RegexWithMatchGroups might have

  • T::HasMatchGroup::<0>::Output,
  • T::HasMatchGroup::<1>::Output,
  • T::HasMatchGroup::<2>::Output,
  • ...
  • T::HasMatchGroup::<{T::RegexWithMatchGroups::MATCH_GROUPS - 1}>::Output.

And there's a potential interaction with the adhoc keyword that I thought up in https://internals.rust-lang.org/t/better-enums/16692.

// It defines a tuple of size `T::RegexWithMatchGroups::MATCH_GROUPS` with said types
let s: (adhoc for <const N: usize in 0..T::RegexWithMatchGroups::MATCH_GROUPS> T::HasMatchGroup::<N>::Output) = (adhoc for <const N: usize in 0..T::RegexWithMatchGroups::MATCH_GROUPS>  {
  let val: <T::HasMatchGroup::<N>::Output>;
  // init and return val
})

Above, (adhoc for <const N: usize in 0..T::RegexWithMatchGroups::MATCH_GROUPS> T::HasMatchGroup::<N>::Output) is a tuple with length T::RegexWithMatchGroups::MATCH_GROUPS and types T::HasMatchGroup::<N>::Output where N iterates in the index range.

And

(adhoc for <const N: usize in 0..T::RegexWithMatchGroups::MATCH_GROUPS>  {
  let val: T::HasMatchGroup::<N>::Output;
  // init and return val
})

is a map-like heterogeneous initializer.

Syntax

adhoc for i in 0..T::RegexWithMatchGroups::MATCH_GROUPS {
  println!("{}", s.{i});
}

could be used for basic heterogeneous iteration rather than intialization. Here s.{i} is a syntax for heterogeneous "indexing" into a tuple.

I realized that such tuple syntax is similar to Python's list comprehensions.