5

Consider the classic example of a const-generic datastructure: a square matrix.

struct Matrix<T, const N: usize> {
    inner: [[T; N]; N]
}

I'd like to return a structure whose const parameter is dynamically defined:

fn read_matrix() -> ??? {
    let n: usize = todo!() // the N is decided dynamically
    let r: Box<Matrix<u8, {n}>> = todo!();
    r
}

but:

  • Rust will complain that n is not a constant
  • I cannot write an appropriate return type :fn read_matrix<const N: usize>() -> Matrix<u8, N> is not adequate, as it lets the caller choose the N, where I want N to be determined in runtime.

I can work around the second limitation by defining a trait:

trait DynamiMatrix {
   fn size(&self) -> usize;
   fn some_method(&self);
   ...
}

impl<T, const N: usize> DynamicMatrix for Matrix<T,N> {
   fn size(&self) -> usize { N };
   fn some_method(&self){ ... }
   ...
}

But, for construction, the best I can try is:

fn read_array_pair() -> Box<dyn DynamicMatrix> {
  let n: usize = todo!();
  let m = Box::new(Matrix { inner: [[0; n]; n] });
  todo!(); // fill up m
  m
}

and Rust will still complain that n is not constant.

Is there any way to achieve this? If possible without falling back to nested Vecs, because i'd like my square invariant to be enforced?

3
  • Even if Rust supported this feature (which I don't think it does) you could not bind a const generic to a variable declared with let: you'd need to make it a const. You can't have a const generic determined at runtime. Not without dependent types, anyway Commented Aug 24, 2021 at 13:22
  • 1
    In other words, rhetorically, Rust could support something like fn read_matrix() -> Matrix<T; impl const usize> {...} and the existential impl const usize could be determined by the content of the function: but it would still have to be compile-time resolvable to some particular N, so you couldn't run arbitrary code to compute it like you appear to be doing here. Commented Aug 24, 2021 at 13:26
  • @trentcl yeah, that's what I figured, but I hoped it would be possible to emulate even a limited form of dependent types using trait objects. Commented Aug 24, 2021 at 13:32

1 Answer 1

6

Const parameters were deliberately designed so that they are always known at compile time. Just like most information about types in a program, the compiler will erase them without keeping this information at run-time. So the short answer is no, and it is unlikely that a direct means of specifying this kind of const parameter at run-time will ever be featured.

However, there are known workarounds to creating generic structures that may either contain compile-time or run-time information, and they even predate const parameters.

Consider this simplified definition of ndarray::ArrayBase:

pub struct ArrayBase<S, D> {
    /// Data buffer / ownership information. (If owned, contains the data
    /// buffer; if borrowed, contains the lifetime and mutability.)
    data: S,
    /// The lengths of the axes.
    dim: D,
    /// The element count stride per axis.
    strides: D,
}

This definition is parameterized over its source of elements S as well as its dimensionality D. D, often implemented through the primitive Dim, will then be generic over both situations:

  • For a fixed number of dimensions such as in Array2, D = Ix2, enabling the user to pass a [usize; 2] to index an element in the array.
  • If the number of dimensions is unknown at compile time, there is ArrayD, in which D = IxDyn and users can pass anything which Deref's to a [usize] for indexing.

The conclusion is that you may be interested in changing the design of your structs and traits so that these details (whether inferred at compile-time or at run-time) are encoded in a type parameter instead of a const parameter.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.