From f07b828d6710f00208f0ac65d4fd78a535615014 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 9 Jan 2021 09:24:38 -0800 Subject: [PATCH] Updates from review. --- src/items/generics.md | 54 ++++++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/items/generics.md b/src/items/generics.md index 1a89d878e..ab264cc95 100644 --- a/src/items/generics.md +++ b/src/items/generics.md @@ -43,8 +43,9 @@ struct Ref<'a, T> where T: 'a { r: &'a T } struct InnerArray([T; N]); ``` -The generic parameters are in scope within the item definition where they are -declared. +Generic parameters are in scope within the item definition where they are +declared. Note that they are not in scope for items declared within the body +of a function as described in [item declarations]. [References], [raw pointers], [arrays], [slices][arrays], [tuples], and [function pointers] have lifetime or type parameters as well, but are not @@ -52,7 +53,7 @@ referred to with path syntax. ### Const generics -Const generic parameters allow items to be generic over constant values. The +*Const generic parameters* allow items to be generic over constant values. The const identifier introduces a name for the constant parameter, and all instances of the item must be instantiated with a value of the given type. @@ -62,11 +63,10 @@ instances of the item must be instantiated with a value of the given type. 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 can generally be used anywhere a [const item] can be used, -with the exception of the definition of any [item] within the body of a -function, and can only be used as standalone expressions in [types] and -[array repeat expressions] (described below). That is, they are allowed in the -following places: +Const parameters can be used anywhere a [const item] can be used, with the +exception that when used in a [type] or [array repeat expression], it must be +standalone (as described below). That is, they are allowed in the following +places: 1. As an applied const to any type which forms a part of the signature of the item in question. @@ -121,7 +121,7 @@ fn foo() { ``` As a further restriction, const parameters may only appear as a standalone -argument inside of [types] and [array repeat expressions]. In those contexts, +argument inside of a [type] or [array repeat expression]. In those contexts, they may only be used as a single segment [path expression], possibly inside a [block] (such as `N` or `{N}`). That is, they cannot be combined with other expressions. @@ -141,9 +141,10 @@ A const argument in a [path] specifies the const value to use for that item. The argument must be a [const expression] of the type ascribed to the const parameter. The const expression must be a [block expression][block] (surrounded with braces) unless it is a single path segment (an [IDENTIFIER]) -or a [literal] (with a possibly leading `-` token). This syntactic restriction -is necessary to avoid requiring infinite lookahead when parsing an expression -inside of a type. +or a [literal] (with a possibly leading `-` token). + +> **Note**: This syntactic restriction is necessary to avoid requiring +> infinite lookahead when parsing an expression inside of a type. ```rust fn double() { @@ -166,6 +167,10 @@ When there is ambiguity if a generic argument could be resolved as either a type or const argument, it is always resolved as a type. Placing the argument in a block expression can force it to be interpreted as a const argument. + + ```rust,compile_fail type N = u32; struct Foo; @@ -189,6 +194,26 @@ struct Baz; struct Biz<'a>; ``` +When resolving a trait bound obligation, the exhaustiveness of all +implementations of const parameters is not considered when determining if the +bound is satisfied. For example, in the following, even though all possible +const values for the `bool` type are implemented, it is still an error that +the trait bound is not satisfied: + +```rust,compile_fail +struct Foo; +trait Bar {} +impl Bar for Foo {} +impl Bar for Foo {} + +fn needs_bar(_: impl Bar) {} +fn generic() { + let v = Foo::; + needs_bar(v); // ERROR: trait bound `Foo: Bar` is not satisfied +} +``` + + ## Where clauses > **Syntax**\ @@ -262,7 +287,7 @@ struct Foo<#[my_flexible_clone(unbounded)] H> { [_Type_]: ../types.md#type-expressions [_TypeParamBounds_]: ../trait-bounds.md -[array repeat expressions]: ../expressions/array-expr.md +[array repeat expression]: ../expressions/array-expr.md [arrays]: ../types/array.md [associated const]: associated-items.md#associated-constants [associated type]: associated-items.md#associated-types @@ -275,6 +300,7 @@ struct Foo<#[my_flexible_clone(unbounded)] H> { [function pointers]: ../types/function-pointer.md [higher-ranked lifetimes]: ../trait-bounds.md#higher-ranked-trait-bounds [implementations]: implementations.md +[item declarations]: ../statements.md#item-declarations [item]: ../items.md [literal]: ../expressions/literal-expr.md [path]: ../paths.md @@ -289,6 +315,6 @@ struct Foo<#[my_flexible_clone(unbounded)] H> { [trait object]: ../types/trait-object.md [traits]: traits.md [type aliases]: type-aliases.md -[types]: ../types.md +[type]: ../types.md [unions]: unions.md [attributes]: ../attributes.md