Skip to content

Commit

Permalink
Merge pull request #901 from lcnr/const-generics
Browse files Browse the repository at this point in the history
document const generics
  • Loading branch information
ehuss authored Jan 6, 2021
2 parents 22c804a + 15ec5a6 commit c81cd07
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
- [Traits](items/traits.md)
- [Implementations](items/implementations.md)
- [External blocks](items/external-blocks.md)
- [Type and lifetime parameters](items/generics.md)
- [Generic parameters](items/generics.md)
- [Associated Items](items/associated-items.md)
- [Visibility and Privacy](visibility-and-privacy.md)

Expand Down
2 changes: 2 additions & 0 deletions src/const_eval.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ also constant expressions and do not cause any [`Drop::drop`][destructors] calls
to be run.

* [Literals].
* [Const parameters].
* [Paths] to [functions] and [constants].
Recursively defining constants is not allowed.
* Paths to [statics]. These are only allowed within the initializer of a static.
Expand Down Expand Up @@ -112,6 +113,7 @@ Conversely, the following are possible in a const function, but not in a const c
[comparison]: expressions/operator-expr.md#comparison-operators
[const functions]: items/functions.md#const-functions
[constants]: items/constant-items.md
[Const parameters]: items/generics.md
[dereference operator]: expressions/operator-expr.md#the-dereference-operator
[destructors]: destructors.md
[enum discriminants]: items/enumerations.md#custom-discriminant-values-for-fieldless-enumerations
Expand Down
59 changes: 49 additions & 10 deletions src/items/generics.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Type and Lifetime Parameters
# Generic parameters

> **<sup>Syntax</sup>**\
> _Generics_ :\
> &nbsp;&nbsp; `<` _GenericParams_ `>`
>
> _GenericParams_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; _LifetimeParams_\
> &nbsp;&nbsp; | ( _LifetimeParam_ `,` )<sup>\*</sup> _TypeParams_
> &nbsp;&nbsp; | ( _LifetimeParam_ `,` )<sup>\*</sup> _TypeParams_\
> &nbsp;&nbsp; | ( _LifetimeParam_ `,` )<sup>\*</sup> ( _TypeParam_ `,` )<sup>\*</sup> _ConstParams_
>
> _LifetimeParams_ :\
> &nbsp;&nbsp; ( _LifetimeParam_ `,` )<sup>\*</sup> _LifetimeParam_<sup>?</sup>
Expand All @@ -18,20 +19,55 @@
> &nbsp;&nbsp; ( _TypeParam_ `,` )<sup>\*</sup> _TypeParam_<sup>?</sup>
>
> _TypeParam_ :\
> &nbsp;&nbsp; [_OuterAttribute_]<sup>?</sup> [IDENTIFIER] ( `:` [_TypeParamBounds_]<sup>?</sup> )<sup>?</sup> ( `=` [_Type_] )<sup>?</sup>
> &nbsp;&nbsp; [_OuterAttribute_]<sup>?</sup> [IDENTIFIER]( `:` [_TypeParamBounds_]<sup>?</sup> )<sup>?</sup> ( `=` [_Type_] )<sup>?</sup>
>
> _ConstParams_:\
> &nbsp;&nbsp; ( _ConstParam_ `,` )<sup>\*</sup> _ConstParam_<sup>?</sup>
>
> _ConstParam_:\
> &nbsp;&nbsp; [_OuterAttribute_]<sup>?</sup> `const` [IDENTIFIER] `:` [_Type_]
Functions, type aliases, structs, enumerations, unions, traits, and
implementations may be *parameterized* by types and lifetimes. These parameters
are listed in angle <span class="parenthetical">brackets (`<...>`)</span>,
implementations may be *parameterized* by types, constants, and lifetimes. These
parameters are listed in angle <span class="parenthetical">brackets (`<...>`)</span>,
usually immediately after the name of the item and before its definition. For
implementations, which don't have a name, they come directly after `impl`.
Lifetime parameters must be declared before type parameters. Some examples of
items with type and lifetime parameters:
The order of generic parameters is restricted to lifetime parameters, then type parameters, and then const parameters.

Some examples of items with type, const, and lifetime parameters:

```rust
fn foo<'a, T>() {}
trait A<U> {}
struct Ref<'a, T> where T: 'a { r: &'a T }
struct InnerArray<T, const N: usize>([T; N]);
```

The only allowed types of const parameters are `u8`, `u16`, `u32`, `u64`, `u128`, `usize`
`i8`, `i16`, `i32`, `i64`, `i128`, `isize`, `char` and `bool`.

Const parameters may only be be used as standalone arguments inside
of [types] and [repeat expressions] but may be freely used elsewhere:

```rust,compile_fail
// ok: standalone argument
fn foo<const N: usize>() -> [u8; N] { todo!() }
// ERROR: generic const operation
fn bar<const N: usize>() -> [u8; N + 1] { todo!() }
```

Unlike type and lifetime parameters, const parameters of types can be used without
being mentioned inside of a parameterized type:

```rust,compile_fail
// ok
struct Foo<const N: usize>;
enum Bar<const M: usize> { A, B }
// ERROR: unused parameter
struct Baz<T>;
struct Biz<'a>;
```

[References], [raw pointers], [arrays], [slices][arrays], [tuples], and
Expand All @@ -55,7 +91,7 @@ referred to with path syntax.
> &nbsp;&nbsp; _ForLifetimes_<sup>?</sup> [_Type_] `:` [_TypeParamBounds_]<sup>?</sup>
>
> _ForLifetimes_ :\
> &nbsp;&nbsp; `for` `<` [_LifetimeParams_](#type-and-lifetime-parameters) `>`
> &nbsp;&nbsp; `for` `<` [_LifetimeParams_](#generic-parameters) `>`
*Where clauses* provide another way to specify bounds on type and lifetime
parameters as well as a way to specify bounds on types that aren't type
Expand All @@ -65,7 +101,7 @@ Bounds that don't use the item's parameters or higher-ranked lifetimes are
checked when the item is defined. It is an error for such a bound to be false.

[`Copy`], [`Clone`], and [`Sized`] bounds are also checked for certain generic
types when defining the item. It is an error to have `Copy` or `Clone`as a
types when defining the item. It is an error to have `Copy` or `Clone` as a
bound on a mutable reference, [trait object] or [slice][arrays] or `Sized` as a
bound on a trait object or slice.

Expand Down Expand Up @@ -112,12 +148,15 @@ struct Foo<#[my_flexible_clone(unbounded)] H> {
[_TypeParamBounds_]: ../trait-bounds.md

[arrays]: ../types/array.md
[const contexts]: ../const_eval.md#const-context
[function pointers]: ../types/function-pointer.md
[references]: ../types/pointer.md#shared-references-
[raw pointers]: ../types/pointer.md#raw-pointers-const-and-mut
[references]: ../types/pointer.md#shared-references-
[repeat expressions]: ../expressions/array-expr.md
[`Clone`]: ../special-types-and-traits.md#clone
[`Copy`]: ../special-types-and-traits.md#copy
[`Sized`]: ../special-types-and-traits.md#sized
[tuples]: ../types/tuple.md
[trait object]: ../types/trait-object.md
[types]: ../types.md
[attributes]: ../attributes.md
26 changes: 24 additions & 2 deletions src/paths.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,32 @@ mod m {
> &nbsp;&nbsp; &nbsp;&nbsp; `<` `>`\
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,`<sup>?</sup> `>`\
> &nbsp;&nbsp; | `<` _GenericArgsTypes_ `,`<sup>?</sup> `>`\
> &nbsp;&nbsp; | `<` _GenericArgsConsts_ `,`<sup>?</sup> `>`\
> &nbsp;&nbsp; | `<` _GenericArgsBindings_ `,`<sup>?</sup> `>`\
> &nbsp;&nbsp; | `<` _GenericArgsTypes_ `,` _GenericArgsBindings_ `,`<sup>?</sup> `>`\
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,`<sup>?</sup> `>`\
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsConsts_ `,`<sup>?</sup> `>`\
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsBindings_ `,`<sup>?</sup> `>`\
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,` _GenericArgsBindings_ `,`<sup>?</sup> `>`
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,` _GenericArgsConsts_ `,`<sup>?</sup> `>`\
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,` _GenericArgsBindings_ `,`<sup>?</sup> `>`\
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsConsts_ `,` _GenericArgsBindings_ `,`<sup>?</sup> `>`\
> &nbsp;&nbsp; | `<` _GenericArgsTypes_ `,` _GenericArgsConsts_ `,` _GenericArgsBindings_ `,`<sup>?</sup> `>`\
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,` _GenericArgsConsts_ `,` _GenericArgsBindings_ `,`<sup>?</sup> `>`
>
> _GenericArgsLifetimes_ :\
> &nbsp;&nbsp; [_Lifetime_] (`,` [_Lifetime_])<sup>\*</sup>
>
> _GenericArgsTypes_ :\
> &nbsp;&nbsp; [_Type_] (`,` [_Type_])<sup>\*</sup>
>
> _GenericArgsConsts_ :\
> &nbsp;&nbsp; _GenericArgsConst_ (`,` _GenericArgsConst_)<sup>\*</sup>
>
> _GenericArgsConst_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; [_BlockExpression_]\
> &nbsp;&nbsp; | [_LiteralExpression_]\
> &nbsp;&nbsp; | `-` [_LiteralExpression_]\
> &nbsp;&nbsp; | [_SimplePathSegment_]
>
> _GenericArgsBindings_ :\
> &nbsp;&nbsp; _GenericArgsBinding_ (`,` _GenericArgsBinding_)<sup>\*</sup>
>
Expand All @@ -81,6 +95,9 @@ ambiguity with the less-than operator. This is colloquially known as "turbofish"
Vec::<u8>::with_capacity(1024);
```

Const arguments must be surrounded by braces unless they are a
[literal] or a single segment path.

## Qualified paths

> **<sup>Syntax</sup>**\
Expand Down Expand Up @@ -364,9 +381,14 @@ mod without { // ::without
# fn main() {}
```

[_BlockExpression_]: expressions/block-expr.md
[_Expression_]: expressions.md
[_GenericArgs_]: #paths-in-expressions
[_Lifetime_]: trait-bounds.md
[_LiteralExpression_]: expressions/literal-expr.md
[_SimplePathSegment_]: #simple-paths
[_Type_]: types.md#type-expressions
[literal]: expressions/literal-expr.md
[item]: items.md
[variable]: variables.md
[implementations]: items/implementations.md
Expand Down

0 comments on commit c81cd07

Please sign in to comment.