From f69b0128462670e040d98e43c3c067031e7c92bf Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 7 Mar 2019 16:04:57 -0500 Subject: [PATCH] markdown fixes for 7.3 proposals These were: 1. adding `csharp` as the language identifier. 1. making relative links to content published on docs.microsoft.com 1. small grammar fixes. --- proposals/csharp-7.3/auto-prop-field-attrs.md | 8 +- proposals/csharp-7.3/blittable.md | 15 ++-- .../expression-variables-in-initializers.md | 2 +- .../indexing-movable-fixed-fields.md | 7 +- proposals/csharp-7.3/pattern-based-fixed.md | 77 +++++++++---------- .../csharp-7.3/ref-local-reassignment.md | 4 +- .../stackalloc-array-initializers.md | 12 +-- proposals/csharp-7.3/tuple-equality.md | 4 +- 8 files changed, 60 insertions(+), 69 deletions(-) diff --git a/proposals/csharp-7.3/auto-prop-field-attrs.md b/proposals/csharp-7.3/auto-prop-field-attrs.md index c34222f..5b4e213 100644 --- a/proposals/csharp-7.3/auto-prop-field-attrs.md +++ b/proposals/csharp-7.3/auto-prop-field-attrs.md @@ -15,7 +15,7 @@ Currently it is not possible to apply attributes to the backing fields of auto-i In short, the following would be legal C# and not produce a warning: -```cs +```csharp [Serializable] public class Foo { @@ -26,7 +26,7 @@ public class Foo This would result in the field-targeted attributes being applied to the compiler-generated backing field: -```cs +```csharp [Serializable] public class Foo { @@ -43,7 +43,7 @@ public class Foo As mentioned, this brings parity with event syntax from C# 1.0 as the following is already legal and behaves as expected: -```cs +```csharp [Serializable] public class Foo { @@ -67,5 +67,3 @@ There are two potential drawbacks to implementing this change: [unresolved]: #unresolved-questions ## Design meetings - - diff --git a/proposals/csharp-7.3/blittable.md b/proposals/csharp-7.3/blittable.md index ee23acf..d47ca63 100644 --- a/proposals/csharp-7.3/blittable.md +++ b/proposals/csharp-7.3/blittable.md @@ -10,14 +10,14 @@ The unmanaged constraint feature will give language enforcement to the class of The primary motivation is to make it easier to author low level interop code in C#. Unmanaged types are one of the core building blocks for interop code, yet the lack of support in generics makes it impossible to create re-usable routines across all unmanaged types. Instead developers are forced to author the same boiler plate code for every unmanaged type in their library: -``` c# +```csharp int Hash(Point point) { ... } int Hash(TimeSpan timeSpan) { ... } ``` To enable this type of scenario the language will be introducing a new constraint: unmanaged: -``` c# +```csharp void Hash(T value) where T : unmanaged { ... @@ -26,7 +26,7 @@ void Hash(T value) where T : unmanaged This constraint can only be met by types which fit into the unmanaged type definition in the C# language spec. Another way of looking at it is that a type satisfies the unmanaged constraint iff it can also be used as a pointer. -``` c# +```csharp Hash(new Point()); // Okay Hash(42); // Okay Hash("hello") // Error: Type string does not satisfy the unmanaged constraint @@ -34,8 +34,7 @@ Hash("hello") // Error: Type string does not satisfy the unmanaged constraint Type parameters with the unmanaged constraint can use all the features available to unmanaged types: pointers, fixed, etc ... - -``` c# +```csharp void Hash(T value) where T : unmanaged { // Okay @@ -48,7 +47,7 @@ void Hash(T value) where T : unmanaged This constraint will also make it possible to have efficient conversions between structured data and streams of bytes. This is an operation that is common in networking stacks and serialization layers: -``` c# +```csharp Span Convert(ref T value) where T : unmanaged { ... @@ -71,7 +70,7 @@ Compiler generated instance fields, such as those backing auto-implemented prope For example: -``` c# +```csharp // Unmanaged type struct Point { @@ -121,7 +120,7 @@ There are a couple of alternatives to consider: The F# language encodes the constraint in the signature file which means C# cannot re-use their representation. A new attribute will need to be chosen for this constraint. Additionally a method which has this constraint must be protected by a mod-req. ### Blittable vs. Unmanaged -The F# language has a very [similar feature](https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/generics/constraints) which uses the keyword unmanaged. The blittable name comes from the use in Midori. May want to look to precedence here and use unmanaged instead. +The F# language has a very [similar feature](https://docs.microsoft.com/dotnet/articles/fsharp/language-reference/generics/constraints) which uses the keyword unmanaged. The blittable name comes from the use in Midori. May want to look to precedence here and use unmanaged instead. **Resolution** The language decide to use unmanaged diff --git a/proposals/csharp-7.3/expression-variables-in-initializers.md b/proposals/csharp-7.3/expression-variables-in-initializers.md index f591d85..50a6ed3 100644 --- a/proposals/csharp-7.3/expression-variables-in-initializers.md +++ b/proposals/csharp-7.3/expression-variables-in-initializers.md @@ -1,4 +1,4 @@ -# expression variables in initializers +# Expression variables in initializers ## Summary [summary]: #summary diff --git a/proposals/csharp-7.3/indexing-movable-fixed-fields.md b/proposals/csharp-7.3/indexing-movable-fixed-fields.md index a151010..7bcec64 100644 --- a/proposals/csharp-7.3/indexing-movable-fixed-fields.md +++ b/proposals/csharp-7.3/indexing-movable-fixed-fields.md @@ -1,4 +1,3 @@ - # Indexing `fixed` fields should not require pinning regardless of the movable/unmovable context. # The change has the size of a bug fix. It can be in 7.3 and does not conflict with whatever direction we take further. @@ -6,7 +5,7 @@ This change is only about allowing the following scenario to work even though `s NOTE: in either case, it still requires `unsafe` context. It is possible to read uninitialized data or even out of range. That is not changing. -```C# +```csharp unsafe struct S { public fixed int myFixedField[10]; @@ -27,7 +26,7 @@ The main “challenge” that I see here is how to explain the relaxation in the In particular, since the following would still need pinning. (because `s` is moveable and we explicitly use the field as a pointer) -```C# +```csharp unsafe struct S { public fixed int myFixedField[10]; @@ -48,5 +47,3 @@ class Program One reason why we require pinning of the target when it is movable is the artifact of our code generation strategy, - we always convert to an unmanaged pointer and thus force the user to pin via `fixed` statement. However, conversion to unmanaged is unnecessary when doing indexing. The same unsafe pointer math is equally applicable when we have the receiver in the form of a managed pointer. If we do that, then the intermediate ref is managed (GC-tracked) and the pinning is unnecessary. The change https://github.com/dotnet/roslyn/pull/24966 is a prototype PR that relaxes this requirement. - - diff --git a/proposals/csharp-7.3/pattern-based-fixed.md b/proposals/csharp-7.3/pattern-based-fixed.md index 959b3be..c2598ac 100644 --- a/proposals/csharp-7.3/pattern-based-fixed.md +++ b/proposals/csharp-7.3/pattern-based-fixed.md @@ -10,7 +10,7 @@ Introduce a pattern that would allow types to participate in `fixed` statements. The language provides a mechanism for pinning managed data and obtain a native pointer to the underlying buffer. -```C# +```csharp fixed(byte* ptr = byteArray) { // ptr is a native pointer to the first element of the array @@ -39,12 +39,12 @@ I think the above could be satisfied by recognizing a specially named ref-return In order to be used by the `fixed` statement the following conditions must be met: -1) There is only one such member provided for a type. -1) Returns by `ref` or `ref readonly`. +1. There is only one such member provided for a type. +1. Returns by `ref` or `ref readonly`. (`readonly` is permitted so that authors of immutable/readonly types could implement the pattern without adding writeable API that could be used in safe code) -1) T is an unmanaged type. +1. T is an unmanaged type. (since `T*` becomes the pointer type. The restriction will naturally expand if/when the notion of "unmanaged" is expanded) -1) Returns managed `nullptr` when there is no data to pin – probably the cheapest way to convey emptiness. +1. Returns managed `nullptr` when there is no data to pin – probably the cheapest way to convey emptiness. (note that “” string returns a ref to '\0' since strings are null-terminated) Alternatively for the `#3` we can allow the result in empty cases be undefined or implementation-specific. @@ -52,49 +52,46 @@ That, however, may make the API more dangerous and prone to abuse and unintended ## *Translation* ## -```C# - fixed(byte* ptr = thing) - { - // - } +```csharp +fixed(byte* ptr = thing) +{ + // +} ``` becomes the following pseudocode (not all expressible in C#) -```C# +```csharp +byte* ptr; +// specially decorated "pinned" IL local slot, not visible to user code. +pinned ref byte _pinned; - byte* ptr; - // specially decorated "pinned" IL local slot, not visible to user code. - pinned ref byte _pinned; - - try +try +{ + // NOTE: null check is omitted for value types + // NOTE: `thing` is evaluated only once (temporary is introduced if necessary) + if (thing != null) { - // NOTE: null check is omitted for value types - // NOTE: `thing` is evaluated only once (temporary is introduced if necessary) - if (thing != null) - { - // obtain and "pin" the reference - _pinned = ref thing.GetPinnableReference(); + // obtain and "pin" the reference + _pinned = ref thing.GetPinnableReference(); - // unsafe cast in IL - ptr = (byte*)_pinned; - } - else - { - ptr = default(byte*); - } - - // + // unsafe cast in IL + ptr = (byte*)_pinned; } - finally // finally can be omitted when not observable + else { - // "unpin" the object - _pinned = nullptr; + ptr = default(byte*); } + // +} +finally // finally can be omitted when not observable +{ + // "unpin" the object + _pinned = nullptr; +} ``` - ## Drawbacks [drawbacks]: #drawbacks @@ -105,11 +102,11 @@ becomes the following pseudocode (not all expressible in C#) Users can introduce GetPinnableReference or similar member and use it as -```C# - fixed(byte* ptr = thing.GetPinnableReference()) - { - // - } +```csharp +fixed(byte* ptr = thing.GetPinnableReference()) +{ + // +} ``` There is no solution for `System.String` if alternative solution is desired. diff --git a/proposals/csharp-7.3/ref-local-reassignment.md b/proposals/csharp-7.3/ref-local-reassignment.md index 0e22aa0..429ce7b 100644 --- a/proposals/csharp-7.3/ref-local-reassignment.md +++ b/proposals/csharp-7.3/ref-local-reassignment.md @@ -4,7 +4,7 @@ In C# 7.3, we add support for rebinding the referent of a ref local variable or We add the following to the set of `assignment_operator`s. -``` antlr +```antlr assignment_operator : '=' 'ref' ; @@ -24,4 +24,4 @@ The safety rules for this operator are: - For a ref reassignment `e1 = ref e2`, the *ref-safe-to-escape* of `e2` must be at least as wide a scope as the *ref-safe-to-escape* of `e1`. -Where *ref-safe-to-escape* is defined in https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.2/span-safety.md +Where *ref-safe-to-escape* is defined in [Safety for ref-like types](../csharp-7.2/span-safety.md) diff --git a/proposals/csharp-7.3/stackalloc-array-initializers.md b/proposals/csharp-7.3/stackalloc-array-initializers.md index b1e45c0..e6ab8de 100644 --- a/proposals/csharp-7.3/stackalloc-array-initializers.md +++ b/proposals/csharp-7.3/stackalloc-array-initializers.md @@ -1,9 +1,9 @@ -# Stackalloc array initializers. +# Stackalloc array initializers ## Summary [summary]: #summary -Allow array initializer syntax to be used with `stackalloc` +Allow array initializer syntax to be used with `stackalloc`. ## Motivation [motivation]: #motivation @@ -11,13 +11,13 @@ Allow array initializer syntax to be used with `stackalloc` Ordinary arrays can have their elements initialized at creation time. It seems reasonable to allow that in `stackalloc` case. The question of why such syntax is not allowed with `stackalloc` arises fairly frequently. -See, for example, https://github.com/dotnet/csharplang/issues/1112 +See, for example, [#1112](https://github.com/dotnet/csharplang/issues/1112) ## Detailed design Ordinary arrays can be created through the following syntax: -```C# +```csharp new int[3] new int[3] { 1, 2, 3 } new int[] { 1, 2, 3 } @@ -26,7 +26,7 @@ new[] { 1, 2, 3 } We should allow stack allocated arrays be created through: -```C# +```csharp stackalloc int[3] // currently allowed stackalloc int[3] { 1, 2, 3 } stackalloc int[] { 1, 2, 3 } @@ -38,7 +38,7 @@ For example: in the last case the element type is inferred from the initializer NOTE: the feature is not dependent on the target being a `Span`. It is just as applicable in `T*` case, so it does not seem reasonable to predicate it on `Span` case. -## Translation ## +## Translation The naive implementation could just initialize the array right after creation through a series of element-wise assignments. diff --git a/proposals/csharp-7.3/tuple-equality.md b/proposals/csharp-7.3/tuple-equality.md index dc2991a..d1a405f 100644 --- a/proposals/csharp-7.3/tuple-equality.md +++ b/proposals/csharp-7.3/tuple-equality.md @@ -73,5 +73,5 @@ If someone wrote their own `ValueTuple` types with an implementation of the com ---- -Relates to https://github.com/dotnet/csharplang/blob/master/spec/expressions.md#relational-and-type-testing-operators -Relates to https://github.com/dotnet/csharplang/issues/190 +Relates to [relational and type testing operators](../../spec/expressions.md#relational-and-type-testing-operators) +Relates to [#190](https://github.com/dotnet/csharplang/issues/190)