### 3 releases

0.1.3 | Jul 10, 2022 |
---|---|

0.1.2 | May 3, 2022 |

0.1.1 | May 3, 2022 |

#**622** in Development tools

**31** downloads per month

Used in constrained_int

**MIT**license

12KB

# Const Guards [docs.rs]

With

you can express certain compile time constraints on rust's `const_guards`

using the unstable `const_generics`

feature.`generic_const_exprs`

## Documentation

For documentation visit docs.rs.

## Motivation

Consider the following usage of the

method on arrays from the standard library:`first`

`let` array`:` `[``(``)``;` `1``]` `=` `[``(``)``;` `1``]``;`
`let` head`:` `Option``<``&``(``)``>` `=` array`.``first``(``)``;`

Would it be nice if we could just write

`let` head`:` `&``(``)` `=` array`.``first``(``)``;`

since the compiler should know this array has length

at this point.
With const guards we can express such as follows:`1`

`#``[``guard``(``N > 0``)``]`
`fn` `first``<``'a`, T, `const` N`:` `usize``>``(``array``:` `&``'a` [T; N]`)`` ``->` `&``'a` T `{`
`&`array`[``0``]`
`}`

The index call on the array

cannot possible fail because we enforced the length of the array to be `&`array`[``0``]`

at compile time. We could now call it as follows`>` `0`

`let` array`:` `[``(``)``;` `1``]` `=` `[``(``)``;` `1``]``;`
`let` head`:` `&``(``)` `=` `first``(``&`array`)``;`

while the case where the array is actually empty would *fail to compile*:

`let` array`:` `[``(``)``;` `0``]` `=` `[``(``)``;` `0``]``;`
`let` head`:` `&``(``)` `=` `first``(``&`array`)``;`

Finally we could even express this as a trait to make it more accessable:

`trait` `ArrayHead`<T, const N: usize> `{`
`#``[``guard``(``<const N: usize> { N > 0 }``)``]`
`fn` `head``(``&``self``)`` ``->` `&`T`;`
`}`
`impl``<`T, `const` N`:` `usize``>`` ``ArrayHead``<`T, N`>` `for`` [``T`; `N`] `{`
`fn` `head``(``&``self``)`` ``->` `&`T `{`
`&``self``[``0``]`
`}`
`}`
`fn` `main``(``)`` ``{`
`let` array`:` `&``[``(``)``;` `1``]` `=` `&``[``(``)``;` `1``]``;`
`let` head`:` `&``(``)` `=` array`.``head``(``)``;`
`}`

Though, as you can see, we need to introduce generics not introduced by the guarded item explicitly.

## Implementation

Consider this simple example of a const guard:

`fn` `main``(``)`` ``{`
`f``::``<`0`>``(``)`
`}`
`#``[``guard``(``N > 0``)``]`
`fn` `f``<``const` N`:` `usize``>``(``)`` ``{`
`todo!``(``)`
`}`

and have a look at the expanded form:

`struct` `Guard``<``const` U`:` `bool``>``;`
`trait` `Protect` `{``}`
`impl` `Protect ``for`` ``Guard``<`true`>` `{``}`
`fn` `main``(``)`` ``{`
`f``::``<`0`>``(``)`
`}`
`fn` `f``<``const` N`:` `usize``>``(``)``
``where`
`Guard``<``{`
`const` fn `_f_guard``<``const` N`:` `usize``>``(``)` -> `bool` `{`
`if` `!`N `>` `0` `{`
`panic!``(``"`guard evaluated to false`"``)`
`}`
`true`
`}`
`_f_guard``::``<`N`>``(``)`
}`>``:` Protect`,`
`{`
`todo!``(``)`
`}`

## Todo

- Improve error messages
- Write more tests

#### Dependencies

~0.6–1MB

~26K SLoC