# const generics general stuff idk
## Where do const expressions appear / come from
* Types
* Array `[T; C]` -- anonymous constants
* Type parameter `S<{C}>`
* Predicates
* `where T: Foo<C>`
* Definitions
* `const N: Ty = C;`
* Expressions
* `const { expr }` -- inline constant
* "basically" equivalent to `{const N: Ty = expr; N}`
* except that it can refer to generic parameters from the surrounding scope
* `N` (path that refers to a constant)
* `[Expr; C]`
* `N::<{C}>`
* Grammar question
* C = N | Literal | '{' Expr '}'
## Generics
* Extend the set of generics with a const kind
## Const values
* Known value =
* Integer literals
* Allocation ==> ValTree eventually
* note that there are constants that can't be represented with a valtree, those values can appear in the values of statics or constant expressions that don't wind up in types
* Generic parameter `N` / Placeholder `!C`
* Unevaluated `D<Substs...>`
* currently, the `Substs` can be 'lazy'
* used because we don't know the set of parameters to start
* Inference variable `?C`
### Examples
hir -> ty happens [here](https://github.com/rust-lang/rust/blob/41301c3b2371365b753c2ad6a74528a38f3815ce/compiler/rustc_middle/src/ty/consts.rs#L39-L70)
* `Foo<22>` -- the 22 is a integer literal
* `impl<const N: usize> { ... Foo<N> ... }` -- [`ConstKind::Param`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/consts/kind/enum.ConstKind.html#variant.Param)
* `impl<const N: usize> { ... Foo<{N}> ... }` -- [`ConstKind::Param`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/consts/kind/enum.ConstKind.html#variant.Param)
* `... Foo<_> ...` anywhere where types can be inferred -- [`ConstKind::Infer`] but has feature gate and lcnr doesn't like the way it is implemented
* `const N: usize = 22; ... Foo<{N}> ...` -- [`ConstKind::Unevaluated`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/consts/kind/enum.ConstKind.html#variant.Unevaluated) with the def-id of the parameter (the `{N}` in `Foo<{N}>`)
* `Foo< ... >` -- as above for all other cases
## Inference rules
Unifying two constants:
* Known, Known ==> "just do it"
* InfVar, InfVar ==> "just do it"
* InfVar, Uneval ==> Map InfVar to Uneval
* Uneval, Known | Uneval, Uneval ==>
* `ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>),`
* @lcnr note: this is currently too lazy, so we need to change something here (cc https://rust-lang.zulipchat.com/#narrow/stream/260443-project-const-generics/topic/lazy.20norm.20recursive.20impls/near/223825249)
## ConstEquate
```
ConstEquate(C1, C2)? :=
ConstEval(C1)? == ConstEval(C2)?
```
code in trait system
### Unclear
how to extend to generic computations
## ConstEval
```
ConstEval(C)? ==> KnownValue
```
code in [rustc_middle::mir::interpret::queries](https://github.com/rust-lang/rust/blob/master/compiler/rustc_middle/src/mir/interpret/queries.rs)
* Known => done
* InfVar => error
* Uneval(DefId, Substs) =>
* get the MIR for DefId
* evaluate it with Substs in scope
* if this encounters:
* placeholder:
## Niko talking random things
```rust
const fn double(n: usize) -> usize { n * 2 }
const fn square(n: usize) -> usize { n * n }
fn main() {
let mut x = [22; double(2)];
x = [22; square(2)];
}
```
```rust
impl<const C: usize> {
double(C) == C * 2
// this has add'l stability implications:
//
// not just the return value of double(C) but the body
// as well
}
```
## Cycle problems
### Variance computation
* We were evaluating constants to compute variance of a type
* We didn't need to, fixed
### Anonymous constants can reference themselves in predicate
```rust
fn foo<T, const C: usize>()
where T: PartialEq<[u8; C + 1]>
// ^^^^^ anonymous constant
generics(foo) = [T, C]
predicates(foo) = [T: PartialEq<[u8; AC_0]>]
generics(AC_0) = [T, C]
predicates(AC_0) = [T: PartialEq<[u8; AC_0]>] // <-- cycle
```
### Using associated consts in where bounds
https://github.com/rust-lang/rust/issues/79356#issuecomment-772179196
```rust
#![feature(generic_const_exprs)]
trait Foo where [(); Self::N]: {
const N: usize;
}
```
### False inference variable cycles
```rust
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] {
todo!()
}
fn main() {
let mut arr = Default::default();
arr = bind(arr); //~ ERROR mismatched type
}
// Current solution:
// *
// * include a subset of predicates
```
## Evaluatable
`ConstEvaluatable(Unevaluated<'tcx, ()>)`
## Match
## Structural equality
https://github.com/rust-lang/lang-team/issues/94