Skip to content

Commit

Permalink
Replace "the compiler" with "a compiler", part 1.
Browse files Browse the repository at this point in the history
Replace instances of "the compiler" with "a compiler" as it relates to what actions a compiler might take while performing static nullable analysis.
  • Loading branch information
BillWagner committed Dec 3, 2024
1 parent ab92e1f commit 9cde1c0
Showing 1 changed file with 13 additions and 14 deletions.
27 changes: 13 additions & 14 deletions standard/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ Because a simple type aliases a struct type, every simple type has members.
> *Note*: The simple types differ from other struct types in that they permit certain additional operations:
>
> - Most simple types permit values to be created by writing *literals* ([§6.4.5](lexical-structure.md#645-literals)), although C# makes no provision for literals of struct types in general. *Example*: `123` is a literal of type `int` and `'a'` is a literal of type `char`. *end example*
> - When the operands of an expression are all simple type constants, it is possible for the compiler to evaluate the expression at compile-time. Such an expression is known as a *constant_expression* ([§12.23](expressions.md#1223-constant-expressions)). Expressions involving operators defined by other struct types are not considered to be constant expressions
> - When the operands of an expression are all simple type constants, it is possible for a compiler to evaluate the expression at compile-time. Such an expression is known as a *constant_expression* ([§12.23](expressions.md#1223-constant-expressions)). Expressions involving operators defined by other struct types are not considered to be constant expressions
> - Through `const` declarations, it is possible to declare constants of the simple types ([§15.4](classes.md#154-constants)). It is not possible to have constants of other struct types, but a similar effect is provided by static readonly fields.
> - Conversions involving simple types can participate in evaluation of conversion operators defined by other struct types, but a user-defined conversion operator can never participate in evaluation of another user-defined conversion operator ([§10.5.3](conversions.md#1053-evaluation-of-user-defined-conversions)).
>
Expand Down Expand Up @@ -743,13 +743,13 @@ A ***non-nullable reference type*** is a reference type of the form `T`, where `

### 8.9.3 Nullable reference types

A reference type of the form `T?` (such as `string?`) is a ***nullable reference type***. The default null-state of a nullable variable is *maybe null*. The annotation `?` indicates the intent that variables of this type are nullable. The compiler can recognize these intents to issue warnings. When the nullable annotation context is disabled, using this annotation can generate a warning.
A reference type of the form `T?` (such as `string?`) is a ***nullable reference type***. The default null-state of a nullable variable is *maybe null*. The annotation `?` indicates the intent that variables of this type are nullable. A compiler can recognize these intents to issue warnings. When the nullable annotation context is disabled, using this annotation can generate a warning.

### 8.9.4 Nullable context

#### 8.9.4.1 General

Every line of source code has a ***nullable context***. The annotations and warnings flags for the nullable context control nullable annotations ([§8.9.4.3](types.md#8943-nullable-annotations)) and nullable warnings ([§8.9.4.4](types.md#8944-nullable-warnings)), respectively. Each flag can be *enabled* or *disabled*. The compiler can use static flow analysis to determine the null state of any reference variable. A reference variable’s null state ([§8.9.5](types.md#895-nullabilities-and-null-states)) is either *not null*, *maybe null*, or *maybe default*.
Every line of source code has a ***nullable context***. The annotations and warnings flags for the nullable context control nullable annotations ([§8.9.4.3](types.md#8943-nullable-annotations)) and nullable warnings ([§8.9.4.4](types.md#8944-nullable-warnings)), respectively. Each flag can be *enabled* or *disabled*. A compiler can use static flow analysis to determine the null state of any reference variable. A reference variable’s null state ([§8.9.5](types.md#895-nullabilities-and-null-states)) is either *not null*, *maybe null*, or *maybe default*.

The nullable context may be specified within source code via nullable directives ([§6.5.9](lexical-structure.md#659-nullable-directive)) and/or via some implementation-specific mechanism external to the source code. If both approaches are used, nullable directives supersede the settings made via an external mechanism.

Expand Down Expand Up @@ -848,9 +848,9 @@ When both the warning flag and the annotations flag are enabled, the nullable co
When the nullable context is ***enabled***:
- For any reference type `T`, the annotation `?` in `T?` makes `T?` a nullable type, whereas the unannotated `T` is non-nullable.
- The compiler can use static flow analysis to determine the null state of any reference variable. When nullable warnings are enabled, a reference variables null state ([§8.9.5](types.md#895-nullabilities-and-null-states)) is either *not null*, *maybe null*, or *maybe default* and
- A compiler can use static flow analysis to determine the null state of any reference variable. When nullable warnings are enabled, a reference variables null state ([§8.9.5](types.md#895-nullabilities-and-null-states)) is either *not null*, *maybe null*, or *maybe default* and
- The null-forgiving operator `!` ([§12.8.9](expressions.md#1289-null-forgiving-expressions)) sets the null state of its operand to *not null*.
- The compiler can issue a warning if the nullability of a type parameter doesnt match the nullability of its corresponding type argument.
- A compiler can issue a warning if the nullability of a type parameter doesnt match the nullability of its corresponding type argument.
### 8.9.5 Nullabilities and null states
Expand Down Expand Up @@ -892,7 +892,7 @@ A diagnostic can be produced when a variable ([§9.2.1](variables.md#921-general
> }
> ```
The compiler may issue a warning where the parameter that might be null is assigned to a variable that should not be null. If the parameter is null-checked before assignment, the compiler may use that in its nullable state analysis and not issue a warning:
A compiler may issue a warning where the parameter that might be null is assigned to a variable that should not be null. If the parameter is null-checked before assignment, a compiler may use that in its nullable state analysis and not issue a warning:
> <!-- Example: {template:"code-in-class-lib", name:"NullChecked"} -->
> ```csharp
Expand All @@ -912,9 +912,9 @@ The compiler may issue a warning where the parameter that might be null is assig
>
> *end example*
The compiler can update the null state of a variable as part of its analysis.
A compiler can update the null state of a variable as part of its analysis.
> *Example*: The compiler may choose to update the state based on any statements in your program:
> *Example*: A compiler may choose to update the state based on any statements in your program:
>
> <!-- Example: {template:"code-in-class-lib", name:"UpdateStates", expectedWarnings:["CS8602","CS8602"]} -->
> ```csharp
Expand All @@ -936,9 +936,9 @@ The compiler can update the null state of a variable as part of its analysis.
> }
> ```
>
> In the previous example, the compiler may decide that after the statement `int length = p.Length;`, the null-state of `p` is not-null. If it were null, that statement would have thrown a `NullReferenceException`. This is similar to the behavior if the code had been preceded by `if (p == null) throw NullReferenceException();` except that the code as written may produce a warning, the purpose of which is to warn that an exception may be thrown implicitly. *end example*
> In the previous example, a compiler may decide that after the statement `int length = p.Length;`, the null-state of `p` is not-null. If it were null, that statement would have thrown a `NullReferenceException`. This is similar to the behavior if the code had been preceded by `if (p == null) throw NullReferenceException();` except that the code as written may produce a warning, the purpose of which is to warn that an exception may be thrown implicitly. *end example*
Later in the method, the code checks that `s` is not a null reference. The null-state of `s` can change to maybe null after the null-checked block closes. The compiler can infer that `s` is maybe null because the code was written to assume that it might have been null. Generally, when the code contains a null check, the compiler may infer that the value might have been null:
Later in the method, the code checks that `s` is not a null reference. The null-state of `s` can change to maybe null after the null-checked block closes. A compiler can infer that `s` is maybe null because the code was written to assume that it might have been null. Generally, when the code contains a null check, a compiler may infer that the value might have been null:
> *Example*: Each of the following expressions include some form of a null check. The null-state of `o` can change from not null to maybe null after each of these statements:
>
Expand All @@ -961,9 +961,8 @@ Later in the method, the code checks that `s` is not a null reference. The null-
> }
> }
> ```
<!-- markdownlint-disable MD028 -->
Both auto-property and field like event declarations make use of a compiler generated backing field. Null state may assume that assignment to the event or property as assignment to the compiler generated backing field.
Both auto-property and field like event declarations make use of a compiler generated backing field. Null state may assume that assignment to the event or property as assignment to a compiler generated backing field.
> *Example*: A compiler can determine that writing an auto-property or field like event writes the corresponding compiler generated backing field. The null state of the property matches that of the backing field.
>
Expand All @@ -987,9 +986,9 @@ Both auto-property and field like event declarations make use of a compiler gene
> }
> ```
>
> In the previous example, the backing field for the `DisappearingProperty` is set to null when it is read. However, a compiler may assume that reading a property doesn’t change the null state of that expression. *end example*
> In the previous example, the constructor doesn't set `P` to a not null value, and a compiler issues a warning. There's no warning when the `P` property is accessed, because the type of the property is a non nullable reference type. *end example*
The compiler can treat a property ([§15.7](classes.md#157-properties)) as either a variable with state, or as independent get and set accessors ([§15.7.3](classes.md#1573-accessors)).
A compiler can treat a property ([§15.7](classes.md#157-properties)) as either a variable with state, or as independent get and set accessors ([§15.7.3](classes.md#1573-accessors)).
> *Example*: A compiler can choose whether writing to a property changes the null state of reading the property, or if reading a property changes the null state of that property.
>
Expand Down

0 comments on commit 9cde1c0

Please sign in to comment.