From d6e349bd1ce81116605397af1095a231a565cfd5 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Thu, 1 Dec 2022 08:53:45 +0000 Subject: [PATCH] Remove references to pointers within the standard where appropriate. - They're still present in the grammar, and in explanatory paragraphs after relevant grammar sections. - There are references in Annexes B and D, but that feels reasonable. Fixes #676. --- standard/classes.md | 7 ++----- standard/expressions.md | 2 +- standard/types.md | 3 +-- standard/unsafe-code.md | 10 +++++++++- standard/variables.md | 1 - 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/standard/classes.md b/standard/classes.md index 558a062d3..aba4db432 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -140,7 +140,7 @@ A *primary_expression* ([§11.7](expressions.md#117-primary-expressions)) is per In any other context, it is a compile-time error to reference a static class. -> *Note*: For example, it is an error for a static class to be used as a base class, a constituent type ([§14.3.7](classes.md#1437-constituent-types)) of a member, a generic type argument, or a type parameter constraint. Likewise, a static class cannot be used in an array type, a pointer type, a new expression, a cast expression, an is expression, an as expression, a `sizeof` expression, or a default value expression. *end note* +> *Note*: For example, it is an error for a static class to be used as a base class, a constituent type ([§14.3.7](classes.md#1437-constituent-types)) of a member, a generic type argument, or a type parameter constraint. Likewise, a static class cannot be used in an array type, a new expression, a cast expression, an is expression, an as expression, a `sizeof` expression, or a default value expression. *end note* ### 14.2.3 Type parameters @@ -442,8 +442,6 @@ The value type constraint specifies that a type argument used for the type param > *Note*: The `System.Nullable` type specifies the non-nullable value type constraint for `T`. Thus, recursively constructed types of the forms `T??` and `Nullable>` are prohibited. *end note* -Pointer types are never allowed to be type arguments and are not considered to satisfy either the reference type or value type constraints. - If a constraint is a class type, an interface type, or a type parameter, that type specifies a minimal “base type” that every type argument used for that type parameter shall support. Whenever a constructed type or generic method is used, the type argument is checked against the constraints on the type parameter at compile-time. The type argument supplied shall satisfy the conditions described in [§8.4.5](types.md#845-satisfying-constraints). A *class_type* constraint shall satisfy the following rules: @@ -567,7 +565,6 @@ The ***dynamic erasure*** of a type `C` is type `Cₓ` constructed as follows: - If `C` is a nested type `Outer.Inner` then `Cₓ` is a nested type `Outerₓ.Innerₓ`. - If `C` `Cₓ`is a constructed type `G` with type arguments `A¹, ..., Aⁿ` then `Cₓ` is the constructed type `G`. - If `C` is an array type `E[]` then `Cₓ` is the array type `Eₓ[]`. -- If `C` is a pointer type `E*` then `Cₓ` is the pointer type `Eₓ*`. - If `C` is dynamic then `Cₓ` is `object`. - Otherwise, `Cₓ` is `C`. @@ -2961,7 +2958,7 @@ class Customer ### 14.6.10 Extension methods -When the first parameter of a method includes the `this` modifier, that method is said to be an ***extension method***. Extension methods shall only be declared in non-generic, non-nested static classes. The first parameter of an extension method may have no modifiers other than `this`, and the parameter type may not be a pointer type. +When the first parameter of a method includes the `this` modifier, that method is said to be an ***extension method***. Extension methods shall only be declared in non-generic, non-nested static classes. The first parameter of an extension method may have no modifiers other than `this`. > *Example*: The following is an example of a static class that declares two extension methods: > diff --git a/standard/expressions.md b/standard/expressions.md index 69a4511aa..ebe038785 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2580,7 +2580,7 @@ class __Anonymous1 } ``` -where each «Tx» is the type of the corresponding expression «ex». The expression used in a *member_declarator* shall have a type. Thus, it is a compile-time error for an expression in a *member_declarator* to be `null` or an anonymous function. It is also a compile-time error for the expression to have a pointer type ([§22.3](unsafe-code.md#223-pointer-types)). +where each «Tx» is the type of the corresponding expression «ex». The expression used in a *member_declarator* shall have a type. Thus, it is a compile-time error for an expression in a *member_declarator* to be `null` or an anonymous function. The names of an anonymous type and of the parameter to its `Equals` method are automatically generated by the compiler and cannot be referenced in program text. diff --git a/standard/types.md b/standard/types.md index a69ee8f8f..a57b40017 100644 --- a/standard/types.md +++ b/standard/types.md @@ -481,7 +481,7 @@ type_argument ; ``` -A *type_argument* shall not be a pointer type ([§22](unsafe-code.md#22-unsafe-code)). Each type argument shall satisfy any constraints on the corresponding type parameter ([§14.2.5](classes.md#1425-type-parameter-constraints)). +Each type argument shall satisfy any constraints on the corresponding type parameter ([§14.2.5](classes.md#1425-type-parameter-constraints)). ### 8.4.3 Open and closed types @@ -650,4 +650,3 @@ An *unmanaged_type* is any type that isn’t a *reference_type*, a *type_paramet - `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `char`, `float`, `double`, `decimal`, or `bool`. - Any *enum_type*. - Any user-defined *struct_type* that is not a constructed type and contains fields of *unmanaged_type*s only. -- In unsafe code ([§22.2](unsafe-code.md#222-unsafe-contexts)), any *pointer_type* ([§22.3](unsafe-code.md#223-pointer-types)). diff --git a/standard/unsafe-code.md b/standard/unsafe-code.md index cf740e489..fd7521bfe 100644 --- a/standard/unsafe-code.md +++ b/standard/unsafe-code.md @@ -130,7 +130,7 @@ The type specified before the `*` in a pointer type is called the ***referent ty A *pointer_type* may only be used in an *array_type* in an unsafe context ([§22.2](unsafe-code.md#222-unsafe-contexts)). A *non_array_type* is any type that is not itself an *array_type*. -Unlike references (values of reference types), pointers are not tracked by the garbage collector—the garbage collector has no knowledge of pointers and the data to which they point. For this reason a pointer is not permitted to point to a reference or to a struct that contains references, and the referent type of a pointer shall be an *unmanaged_type*. +Unlike references (values of reference types), pointers are not tracked by the garbage collector—the garbage collector has no knowledge of pointers and the data to which they point. For this reason a pointer is not permitted to point to a reference or to a struct that contains references, and the referent type of a pointer shall be an *unmanaged_type*. Pointer types themselves are unmanaged types, so a pointer type may be used as the referent type for another pointer type. The intuitive rule for mixing of pointers and references is that referents of references (objects) are permitted to contain pointers, but referents of pointers are not permitted to contain references. @@ -170,8 +170,16 @@ A *pointer_type* cannot be used as a type argument ([§8.4](types.md#84-construc A *pointer_type* cannot be used as a type of a subexpression of a dynamically bound operation ([§11.3.3](expressions.md#1133-dynamic-binding)). +A *pointer_type* cannot be used as the type of the first parameter in an extension method ([§14.6.10](classes.md#14610-extension-methods)). + A *pointer_type* may be used as the type of a volatile field ([§14.5.4](classes.md#1454-volatile-fields)). +The *dynamic erasure* of a type `E*` is the pointer type with referent type of the dynamic erasure of `E`. + +An expression with a pointer type cannot be used to provide the value in a *member_declarator* within an *anonymous_object_creation_expression* ([§11.7.15.7](expressions.md#117157-anonymous-object-creation-expressions)). + +The default value ([§9.3](variables.md#93-default-values)) for any pointer type is `null`. + > *Note*: Although pointers can be passed as `ref` or `out` parameters, doing so can cause undefined behavior, since the pointer might well be set to point to a local variable that no longer exists when the called method returns, or the fixed object to which it used to point, is no longer fixed. For example: > > diff --git a/standard/variables.md b/standard/variables.md index 621812b14..3c8e874fd 100644 --- a/standard/variables.md +++ b/standard/variables.md @@ -162,7 +162,6 @@ The default value of a variable depends on the type of the variable and is deter - For a variable of a *value_type*, the default value is the same as the value computed by the *value_type*’s default constructor ([§8.3.3](types.md#833-default-constructors)). - For a variable of a *reference_type*, the default value is `null`. -- In an unsafe context, for a variable of a *pointer_type*, the default value is `null`. > *Note*: Initialization to default values is typically done by having the memory manager or garbage collector initialize memory to all-bits-zero before it is allocated for use. For this reason, it is convenient to use all-bits-zero to represent the null reference. *end note*