Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

document const generics #901

Merged
merged 11 commits into from
Jan 6, 2021
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
lcnr marked this conversation as resolved.
Show resolved Hide resolved

> **<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_
Comment on lines +9 to +10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this grammar is no longer correct (see #785). The order of the parameters doesn't matter syntactically.

You don't have to fix it if you don't want to (although that would be nice), I just wanted to make a note of it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

won't do this in that PR, as I don't know what it's expected to look like now.

>
> _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
17 changes: 15 additions & 2 deletions src/paths.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,26 @@ 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; [_Expression_] (`,` [_Expression_])<sup>\*</sup>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is the actual grammar for arguments is it? According to parse_generic_arg I believe it is something like this:

diff --git a/src/paths.md b/src/paths.md
index 9126e5b..47a14ee 100644
--- a/src/paths.md
+++ b/src/paths.md
@@ -70,7 +70,13 @@ mod m {
 > &nbsp;&nbsp; [_Type_] (`,` [_Type_])<sup>\*</sup>
 >
 > _GenericArgsConsts_ :\
-> &nbsp;&nbsp; [_Expression_] (`,` [_Expression_])<sup>\*</sup>
+> &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>
@@ -375,10 +381,13 @@ 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
-[_Expression_]: expressions.md
 [literal]: expressions/literal-expr.md
 [item]: items.md
 [variable]: variables.md

Is that correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, that looks right to me

>
> _GenericArgsBindings_ :\
> &nbsp;&nbsp; _GenericArgsBinding_ (`,` _GenericArgsBinding_)<sup>\*</sup>
>
Expand All @@ -81,6 +89,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.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case this section might not be needed


## Qualified paths

> **<sup>Syntax</sup>**\
Expand Down Expand Up @@ -367,6 +378,8 @@ mod without { // ::without
[_GenericArgs_]: #paths-in-expressions
[_Lifetime_]: trait-bounds.md
[_Type_]: types.md#type-expressions
[_Expression_]: expressions.md
[literal]: expressions/literal-expr.md
[item]: items.md
[variable]: variables.md
[implementations]: items/implementations.md
Expand Down