-
Notifications
You must be signed in to change notification settings - Fork 86
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
Support new stackalloc expression locations #1056
base: draft-v8
Are you sure you want to change the base?
Support new stackalloc expression locations #1056
Conversation
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.
This LGTM @RexJaeschke
@jskeet Let's put this on the agenda for the next meeting to approve.
@@ -277,6 +277,7 @@ In an unsafe context, the set of available implicit conversions ([§10.2](conver | |||
|
|||
- From any *pointer_type* to the type `void*`. | |||
- From the `null` literal ([§6.4.5.7](lexical-structure.md#6457-the-null-literal)) to any *pointer_type*. | |||
- From any *pointer_type* to the type `System.Span<T>`, where `T` is the referent type of *pointer_type*. |
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.
That implicit conversion seems wrong to me. How would it decide the number of elements in the System.Span<T>
?
using System;
public class C {
public unsafe void M() {
int* pointer = stackalloc int[3];
Span<int> span;
// error CS0029: Cannot implicitly convert type 'int*' to 'System.Span<int>'
span = pointer;
}
}
Instead, you should have an implicit conversion only from a stackalloc_expression to a span type.
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.
Likewise error CS0029 here:
Span<int> span = (int*)null;
var
deduces a pointer type, though:
public class C {
public unsafe void M() {
var a = stackalloc int[3];
MustBePointer(ref a); // OK
}
static unsafe void MustBePointer(ref int* p) {}
}
But not when parenthesized:
public class C {
public unsafe void M() {
var a = (stackalloc int[3]);
MustBePointer(ref a); // error CS1503: Argument 1: cannot convert from 'ref System.Span<int>' to 'ref int*'
}
static unsafe void MustBePointer(ref int* p) {}
}
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.
This objection looks reasonable - and if we can just change it to an implicit conversion from stackalloc_expression, I think that should be simple. But I don't know the origin of this change, so that could be missing something.
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.
Agree with @KalleOlaviNiemitalo, the conversion from a pointer must be wrong.
An implicit conversion from a stackalloc_expression to Span<T>
is not required as that is the type of such an expression in safe code, from §12.8.21:
The result of a stackalloc_expression is an instance of type
Span<T>
, whereT
is the unmanaged_type…
In unsafe code it can be a pointer or a Span<T>
, from §23.9:
In an unsafe context if a stackalloc_expression (§12.8.21) occurs as the initializing expression of a local_variable_declaration (§13.6.2), where the local_variable_type is either a pointer type (§23.3) or inferred (
var
), then the result of the stackalloc_expression is a pointer of typeT *
to be beginning of the allocated block, whereT
is the unmanaged_type of the stackalloc_expression.In all other respects the semantics of local_variable_declarations (§13.6.2) and stackalloc_expressions (§12.8.21) in unsafe contexts follow those defined for safe contexts.
The added conversion wouldn’t make sense even in unsafe code, unless the resulting span had infinite length (and couldn’t be passed to safe code!)
Just delete this added conversion.
From discussion, we should reimplement this PR to look more like https://github.com/dotnet/csharplang/blob/main/proposals/csharp-8.0/nested-stackalloc.md - that doesn't talk about a conversion from pointer types, and explains the oddity of the change of type when the expression is parenthesized. |
Neal is going to make the change - either in this PR or in one which supercedes it. |
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.
Removal of the 7.3 restrictions look fine.
The addition of the implicit conversion from a pointer to a Span
needs to go.
@@ -277,6 +277,7 @@ In an unsafe context, the set of available implicit conversions ([§10.2](conver | |||
|
|||
- From any *pointer_type* to the type `void*`. | |||
- From the `null` literal ([§6.4.5.7](lexical-structure.md#6457-the-null-literal)) to any *pointer_type*. | |||
- From any *pointer_type* to the type `System.Span<T>`, where `T` is the referent type of *pointer_type*. |
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.
Agree with @KalleOlaviNiemitalo, the conversion from a pointer must be wrong.
An implicit conversion from a stackalloc_expression to Span<T>
is not required as that is the type of such an expression in safe code, from §12.8.21:
The result of a stackalloc_expression is an instance of type
Span<T>
, whereT
is the unmanaged_type…
In unsafe code it can be a pointer or a Span<T>
, from §23.9:
In an unsafe context if a stackalloc_expression (§12.8.21) occurs as the initializing expression of a local_variable_declaration (§13.6.2), where the local_variable_type is either a pointer type (§23.3) or inferred (
var
), then the result of the stackalloc_expression is a pointer of typeT *
to be beginning of the allocated block, whereT
is the unmanaged_type of the stackalloc_expression.In all other respects the semantics of local_variable_declarations (§13.6.2) and stackalloc_expressions (§12.8.21) in unsafe contexts follow those defined for safe contexts.
The added conversion wouldn’t make sense even in unsafe code, unless the resulting span had infinite length (and couldn’t be passed to safe code!)
Just delete this added conversion.
No description provided.