diff --git a/src/SUMMARY.md b/src/SUMMARY.md index fb0e6574d..bd9cb9ca7 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -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) diff --git a/src/const_eval.md b/src/const_eval.md index b3d087f32..159f0a768 100644 --- a/src/const_eval.md +++ b/src/const_eval.md @@ -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. @@ -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 diff --git a/src/items/generics.md b/src/items/generics.md index ba35e64d2..abb50b47f 100644 --- a/src/items/generics.md +++ b/src/items/generics.md @@ -1,4 +1,4 @@ -# Type and Lifetime Parameters +# Generic parameters > **Syntax**\ > _Generics_ :\ @@ -6,7 +6,8 @@ > > _GenericParams_ :\ >       _LifetimeParams_\ ->    | ( _LifetimeParam_ `,` )\* _TypeParams_ +>    | ( _LifetimeParam_ `,` )\* _TypeParams_\ +>    | ( _LifetimeParam_ `,` )\* ( _TypeParam_ `,` )\* _ConstParams_ > > _LifetimeParams_ :\ >    ( _LifetimeParam_ `,` )\* _LifetimeParam_? @@ -18,20 +19,55 @@ >    ( _TypeParam_ `,` )\* _TypeParam_? > > _TypeParam_ :\ ->    [_OuterAttribute_]? [IDENTIFIER] ( `:` [_TypeParamBounds_]? )? ( `=` [_Type_] )? +>    [_OuterAttribute_]? [IDENTIFIER]( `:` [_TypeParamBounds_]? )? ( `=` [_Type_] )? +> +> _ConstParams_:\ +>    ( _ConstParam_ `,` )\* _ConstParam_? +> +> _ConstParam_:\ +>    [_OuterAttribute_]? `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 brackets (`<...>`), +implementations may be *parameterized* by types, constants, and lifetimes. These +parameters are listed in angle brackets (`<...>`), 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 {} struct Ref<'a, T> where T: 'a { r: &'a T } +struct InnerArray([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() -> [u8; N] { todo!() } + +// ERROR: generic const operation +fn bar() -> [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; +enum Bar { A, B } + +// ERROR: unused parameter +struct Baz; +struct Biz<'a>; ``` [References], [raw pointers], [arrays], [slices][arrays], [tuples], and @@ -55,7 +91,7 @@ referred to with path syntax. >    _ForLifetimes_? [_Type_] `:` [_TypeParamBounds_]? > > _ForLifetimes_ :\ ->    `for` `<` [_LifetimeParams_](#type-and-lifetime-parameters) `>` +>    `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 @@ -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. @@ -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 diff --git a/src/paths.md b/src/paths.md index 821d883d1..47a14ee91 100644 --- a/src/paths.md +++ b/src/paths.md @@ -52,11 +52,16 @@ mod m { >       `<` `>`\ >    | `<` _GenericArgsLifetimes_ `,`? `>`\ >    | `<` _GenericArgsTypes_ `,`? `>`\ +>    | `<` _GenericArgsConsts_ `,`? `>`\ >    | `<` _GenericArgsBindings_ `,`? `>`\ ->    | `<` _GenericArgsTypes_ `,` _GenericArgsBindings_ `,`? `>`\ >    | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,`? `>`\ +>    | `<` _GenericArgsLifetimes_ `,` _GenericArgsConsts_ `,`? `>`\ >    | `<` _GenericArgsLifetimes_ `,` _GenericArgsBindings_ `,`? `>`\ ->    | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,` _GenericArgsBindings_ `,`? `>` +>    | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,` _GenericArgsConsts_ `,`? `>`\ +>    | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,` _GenericArgsBindings_ `,`? `>`\ +>    | `<` _GenericArgsLifetimes_ `,` _GenericArgsConsts_ `,` _GenericArgsBindings_ `,`? `>`\ +>    | `<` _GenericArgsTypes_ `,` _GenericArgsConsts_ `,` _GenericArgsBindings_ `,`? `>`\ +>    | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,` _GenericArgsConsts_ `,` _GenericArgsBindings_ `,`? `>` > > _GenericArgsLifetimes_ :\ >    [_Lifetime_] (`,` [_Lifetime_])\* @@ -64,6 +69,15 @@ mod m { > _GenericArgsTypes_ :\ >    [_Type_] (`,` [_Type_])\* > +> _GenericArgsConsts_ :\ +>    _GenericArgsConst_ (`,` _GenericArgsConst_)\* +> +> _GenericArgsConst_ :\ +>       [_BlockExpression_]\ +>    | [_LiteralExpression_]\ +>    | `-` [_LiteralExpression_]\ +>    | [_SimplePathSegment_] +> > _GenericArgsBindings_ :\ >    _GenericArgsBinding_ (`,` _GenericArgsBinding_)\* > @@ -81,6 +95,9 @@ ambiguity with the less-than operator. This is colloquially known as "turbofish" Vec::::with_capacity(1024); ``` +Const arguments must be surrounded by braces unless they are a +[literal] or a single segment path. + ## Qualified paths > **Syntax**\ @@ -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