From d107c04ca59df9aed1dc15ae54ce49859fb9a03a Mon Sep 17 00:00:00 2001 From: Connor Horman Date: Thu, 12 Sep 2024 10:47:01 -0400 Subject: [PATCH] Add identifier syntax to statements.md --- src/statements-and-expressions.md | 2 ++ src/statements.md | 36 ++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/statements-and-expressions.md b/src/statements-and-expressions.md index fede41196..b7496964c 100644 --- a/src/statements-and-expressions.md +++ b/src/statements-and-expressions.md @@ -1,5 +1,7 @@ # Statements and expressions +r[stmt-expr] + Rust is _primarily_ an expression language. This means that most forms of value-producing or effect-causing evaluation are directed by the uniform syntax category of _expressions_. Each kind of expression can typically _nest_ within each other kind of expression, and rules for evaluation of expressions involve specifying both the value produced by the expression and the order in which its sub-expressions are themselves evaluated. diff --git a/src/statements.md b/src/statements.md index 40f95beca..5ee35d9ab 100644 --- a/src/statements.md +++ b/src/statements.md @@ -1,5 +1,8 @@ # Statements +r[statement] + +r[statement.syntax] > **Syntax**\ > _Statement_ :\ >       `;`\ @@ -8,13 +11,16 @@ >    | [_ExpressionStatement_]\ >    | [_MacroInvocationSemi_] - +r[statement.intro] A *statement* is a component of a [block], which is in turn a component of an outer [expression] or [function]. +r[statement.kind] Rust has two kinds of statement: [declaration statements](#declaration-statements) and [expression statements](#expression-statements). ## Declaration statements +r[statement.decl] + A *declaration statement* is one that introduces one or more *names* into the enclosing statement block. The declared names may denote new variables or new [items][item]. @@ -22,12 +28,20 @@ The two kinds of declaration statements are item declarations and `let` statemen ### Item declarations +r[statement.item] + +r[statement.item.intro] An *item declaration statement* has a syntactic form identical to an [item declaration][item] within a [module]. + +r[statement.item.scope] Declaring an item within a statement block restricts its [scope] to the block containing the statement. The item is not given a [canonical path] nor are any sub-items it may declare. + +r[statement.item.associated-scope] The exception to this is that associated items defined by [implementations] are still accessible in outer scopes as long as the item and, if applicable, trait are accessible. It is otherwise identical in meaning to declaring the item inside a module. +r[statement.item.outer-generics] There is no implicit capture of the containing function's generic parameters, parameters, and local variables. For example, `inner` may not access `outer_var`. @@ -43,6 +57,9 @@ fn outer() { ### `let` statements +r[statement.let] + +r[statement.let.syntax] > **Syntax**\ > _LetStatement_ :\ >    [_OuterAttribute_]\* `let` [_PatternNoTopAlt_] @@ -52,13 +69,21 @@ fn outer() { > † When an `else` block is specified, the > _Expression_ must not be a [_LazyBooleanExpression_], or end with a `}`. +r[statement.let.intro] A *`let` statement* introduces a new set of [variables], given by a [pattern]. The pattern is followed optionally by a type annotation and then either ends, or is followed by an initializer expression plus an optional `else` block. + +r[statement.let.inference] When no type annotation is given, the compiler will infer the type, or signal an error if insufficient type information is available for definite inference. + +r[statement.let.scope] Any variables introduced by a variable declaration are visible from the point of declaration until the end of the enclosing block scope, except when they are shadowed by another variable declaration. +r[statement.let.constraint] If an `else` block is not present, the pattern must be irrefutable. If an `else` block is present, the pattern may be refutable. + +r[statement.let.behavior] If the pattern does not match (this requires it to be refutable), the `else` block is executed. The `else` block must always diverge (evaluate to the [never type]). @@ -75,17 +100,24 @@ let [u, v] = [v[0], v[1]] else { // This pattern is irrefutable, so the compiler ## Expression statements +r[statement.expr] + +r[statement.expr.syntax] > **Syntax**\ > _ExpressionStatement_ :\ >       [_ExpressionWithoutBlock_][expression] `;`\ >    | [_ExpressionWithBlock_][expression] `;`? +r[statement.expr.intro] An *expression statement* is one that evaluates an [expression] and ignores its result. As a rule, an expression statement's purpose is to trigger the effects of evaluating its expression. +r[statement.expr.restriction-semicolon] An expression that consists of only a [block expression][block] or control flow expression, if used in a context where a statement is permitted, can omit the trailing semicolon. This can cause an ambiguity between it being parsed as a standalone statement and as a part of another expression; in this case, it is parsed as a statement. + +r[statement.expr.constraint-block] The type of [_ExpressionWithBlock_][expression] expressions when used as statements must be the unit type. ```rust @@ -118,6 +150,8 @@ if true { ## Attributes on Statements +r[statement.attribute] + Statements accept [outer attributes]. The attributes that have meaning on a statement are [`cfg`], and [the lint check attributes].