-
Notifications
You must be signed in to change notification settings - Fork 92
[Version 9.0] Feature support for target typed new
#1469
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: draft-v9
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2177,8 +2177,8 @@ | |
| A *null_conditional_invocation_expression* is syntactically either a *null_conditional_member_access* ([§12.8.8](expressions.md#1288-null-conditional-member-access)) or *null_conditional_element_access* ([§12.8.13](expressions.md#12813-null-conditional-element-access)) where the final *dependent_access* is an invocation expression ([§12.8.10](expressions.md#12810-invocation-expressions)). | ||
|
|
||
| A *null_conditional_invocation_expression* occurs within the context of a *statement_expression* ([§13.7](statements.md#137-expression-statements)), *anonymous_function_body* ([§12.21.1](expressions.md#12211-general)), or *method_body* ([§15.6.1](classes.md#1561-general)). | ||
|
|
||
| Unlike the syntactically equivalent *null_conditional_member_access* or *null_conditional_element_access*, a *null_conditional_invocation_expression* may be classified as nothing. | ||
|
|
||
| ```ANTLR | ||
| null_conditional_invocation_expression | ||
|
|
@@ -2258,7 +2258,7 @@ | |
| - The *primary_expression* has compile-time type `dynamic`. | ||
| - At least one expression of the *argument_list* has compile-time type `dynamic`. | ||
|
|
||
| In this case the compile-time type of the *element_access* depends on the compile-time type of its *primary_expression*: if it has an array type then the compile-time type is the element type of that array type; otherwise the compile-time type is `dynamic` and the *element_access* is classified as a value of type `dynamic`. The rules below to determine the meaning of the *element_access* are then applied at run-time, using the run-time type instead of the compile-time type of those of the *primary_expression* and *argument_list* expressions which have the compile-time type `dynamic`. If the *primary_expression* does not have compile-time type `dynamic`, then the element access undergoes a limited compile-time check as described in [§12.6.5](expressions.md#1265-compile-time-checking-of-dynamic-member-invocation). | ||
|
|
||
| > *Example*: | ||
| > | ||
|
|
@@ -2548,6 +2548,11 @@ | |
| object_creation_expression | ||
| : 'new' type '(' argument_list? ')' object_or_collection_initializer? | ||
| | 'new' type object_or_collection_initializer | ||
| | target_typed_new | ||
| ; | ||
|
|
||
| target_typed_new | ||
| : 'new' '(' argument_list? ')' object_or_collection_initializer? | ||
| ; | ||
|
|
||
| object_or_collection_initializer | ||
|
|
@@ -2558,6 +2563,10 @@ | |
|
|
||
| The *type* of an *object_creation_expression* shall be a *class_type*, a *value_type*, or a *type_parameter*. The *type* cannot be a *tuple_type* or an abstract or static *class_type*. | ||
|
|
||
| If `type` can be inferred from usage, it can be omitted, as allowed by *target_typed_new*. It is a compile-time error to omit `type` if the type cannot be inferred. A *target_typed_new* expression has no type. However, there is an implicit object-creation conversion (§imp-obj-creation-conv) from a *target_typed_new* expression to every type. It is a compile-time error if a *target_typed_new* is used as an operand of a unary or binary operator, or if it is used where it is not subject to an object-creation conversion. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "If For example, if I have: void M(int x) { ... }
void M(Guid g) { ... }... then can I write
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (I strongly suspect that clarifying this will be the biggest change required for this feature. I don't know whether we'll need to consider everywhere that target_typed_new can exist...)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one will be tough. Your example generates CS0121: The call is ambiguous between The example in the speclet shows a method with several overloads, Now, if you use this: |
||
|
|
||
| If `type` is present, let `T` be that type; otherwise, let `T` be the implied type. | ||
|
|
||
| The optional *argument_list* ([§12.6.2](expressions.md#1262-argument-lists)) is permitted only if the *type* is a *class_type* or a *struct_type*. | ||
|
|
||
| An object creation expression can omit the constructor argument list and enclosing parentheses provided it includes an object initializer or collection initializer. Omitting the constructor argument list and enclosing parentheses is equivalent to specifying an empty argument list. | ||
|
|
@@ -2566,7 +2575,7 @@ | |
|
|
||
| If any of the arguments in the optional *argument_list* has the compile-time type `dynamic` then the *object_creation_expression* is dynamically bound ([§12.3.3](expressions.md#1233-dynamic-binding)) and the following rules are applied at run-time using the run-time type of those arguments of the *argument_list* that have the compile-time type `dynamic`. However, the object creation undergoes a limited compile-time check as described in [§12.6.5](expressions.md#1265-compile-time-checking-of-dynamic-member-invocation). | ||
|
|
||
| The binding-time processing of an *object_creation_expression* of the form `new T(A)`, where `T` is a *class_type*, or a *value_type*, and `A` is an optional *argument_list*, consists of the following steps: | ||
| The binding-time processing of an *object_creation_expression* of the form `new T(A)`, where the specified or implied type `T` is a *class_type*, or a *value_type*, and `A` is an optional *argument_list*, consists of the following steps: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A target-typed new expression isn't "of the form
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (Existing potential problem) Should this include If it's not intended to exclude that case, why use "of the form" at all? |
||
|
|
||
| - If `T` is a *value_type* and `A` is not present: | ||
| - The *object_creation_expression* is a default constructor invocation. The result of the *object_creation_expression* is a value of type `T`, namely the default value for `T` as defined in [§8.3.3](types.md#833-default-constructors). | ||
|
|
@@ -2581,7 +2590,7 @@ | |
|
|
||
| Even if the *object_creation_expression* is dynamically bound, the compile-time type is still `T`. | ||
|
|
||
| The run-time processing of an *object_creation_expression* of the form new `T(A)`, where `T` is *class_type* or a *struct_type* and `A` is an optional *argument_list*, consists of the following steps: | ||
| The run-time processing of an *object_creation_expression* of the form `new T(A)`, where the specified or implied type `T` is *class_type* or a *struct_type* and `A` is an optional *argument_list*, consists of the following steps: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another example of the same kind of thing. |
||
|
|
||
| - If `T` is a *class_type*: | ||
| - A new instance of class `T` is allocated. If there is not enough memory available to allocate the new instance, a `System.OutOfMemoryException` is thrown and no further steps are executed. | ||
|
|
@@ -3109,8 +3118,8 @@ | |
| ### 12.8.18 The typeof operator | ||
|
|
||
| The `typeof` operator is used to obtain the `System.Type` object for a type. | ||
|
|
||
| ```ANTLR | ||
| typeof_expression | ||
| : 'typeof' '(' type ')' | ||
| | 'typeof' '(' unbound_type_name ')' | ||
|
|
@@ -3394,7 +3403,7 @@ | |
| - one of the following value types: `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `char`, `float`, `double`, `decimal`, `bool,`; or | ||
| - any enumeration type. | ||
|
|
||
| ### 12.8.22 Stack allocation | ||
|
|
||
| A stack allocation expression allocates a block of memory from the execution stack. The ***execution stack*** is an area of memory where local variables are stored. The execution stack is not part of the managed heap. The memory used for local variable storage is automatically recovered when the current function returns. | ||
|
|
||
|
|
@@ -6721,7 +6730,7 @@ | |
| ## 12.23 Assignment operators | ||
|
|
||
| ### 12.23.1 General | ||
|
|
||
| All but one of the assignment operators assigns a new value to a variable, a property, an event, or an indexer element. The exception, `= ref`, assigns a variable reference ([§9.5](variables.md#95-variable-references)) to a reference variable ([§9.7](variables.md#97-reference-variables-and-returns)). | ||
|
|
||
| ```ANTLR | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this include pointer types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, because a pointer type can't be used in an object creation expression. See https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#1281721-general