-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Closed
Description
Spec: https://github.com/dotnet/csharplang/blob/main/proposals/low-level-struct-improvements.md
Tracking issue in runtime repo: dotnet/runtime#63768
Championed issue: dotnet/csharplang#1147
Guideline for addressing remaining issues:
- Base local testing off of 17.4 branch (verify behavior shipping in .NET 7)
- Base PRs on main (verify behavior in VS 17.5).
- Issues which we plan to address in 17.5, open new standalone issues and check-off in here
- Scenarios which we do not plan to test, either delete the line or add ❌ at start of line at your discretion.
Compiler
- spec: add grammar
- spec:
scopedcan only be applied to areftype or a type that is aref struct - import of
reffield when runtime feature flag is missing:RefFieldTests.RuntimeFeature - ref assemblies and consumption by old compilers
-
reffields are emitted asreffor reference assemblies (no change). Note that our ability to control what old compilers actually do with these fields is somewhat limited. We prefer if it just gives a use site error when the ref field is used, but may not be able to make changes if the behavior does not end up being ideal. (RefFieldTests.RefAssembly) -
ref assemblies which contain ref fields not consumable by old compilers (even if ref field is private)(not a supported scenario) -
Test metadata compatibility with previous compiler release (C# and VB)(not a supported scenario)
-
- check internal enumerations of local variable kinds (ensure that all LocalDeclarationKind values which can by by-ref or ref struct are given correct val escape and ref escape, with or without
scopedkeyword) Supportscopedmodifier for other local declarations #62039 - spec: OHI
-
manual test of C++/CLI (can reference local assemblies with ref fields)(known issue, tracked by C++/CLI team) - spec
- add to compiler test plan
-
-langversion:11- for
reffield declarations in source (also requires RuntimeFeature.ByRefFields) - for use-site of
reffields from metadata or compilation reference (RefFieldTests.LanguageVersionDiagnostics)
- for
- updated escape rules enabled by
-
-langversion:11or -
System.Runtime.CompilerServices.RuntimeFeature.ByRefFieldsEnable updated escape rules ifSystem.Runtime.CompilerServices.RuntimeFeature.ByRefFieldsexists #62131
-
-
refandref readonlyfields forref structonly- declaration error for
reffield inclass,struct,recordin source No error for ref fields in non-ref structs #62596 - declaration error for
refparameter inrecordin source - use-site error for
reffield inclassorstructfrom metadata for C# and VB Report use-site error using ref field from type other thanref structin C# #64682
- declaration error for
- field must be declared
readonly refinreadonly ref struct - escape analysis within
readonlymethods (RefFieldTests.MethodArgumentsMustMatch_13) -
readonly refemitted asinitonly -
ref readonlyemitted withSystem.Runtime.CompilerServices.IsReadOnlyAttribute -
ref structwith areffield is not consideredunmanagedstackalloc should be disallowed for structs with ref fields #63104 - field initializers:
-
refinitializer Syntax error parsing field initializer withrefexpression #64720 - error reported for value initializer Ref field initializer is treated as a value assignment #64725
-
ref structfield initializer safe-to-escape: see #60577 comment
-
-
reffield modifiers-
static reffields disallowed -
const reffields disallowed -
volatile reffields disallowed -
fixed reffields disallowed
-
-
refauto-properties disallowedref T P0 { get; } // error ref T P1 { get; set; } // error ref T P2 { get; init; } // error
-
refin object initializers supported:new S { F = ref t }Support ref field assignment in object initializers #62120 -
reffield of the containing type: Allow ref field of the containing type #62098ref struct R<T> { public ref R<T> Next; }
-
_ = s.F;should throwNullReferenceExceptionif ref field isnull- see Record read of ref local even if value is discarded #60910 (comment) -
scopedas type name- supported with
-langversion:10and earlier for compat - error with
-langversion:11
- supported with
-
scopedmodifier roundtripped to metadata -
scopedconsidered in overrides and interface implementation - conversion errors for mismatch of
scoped- for delegate conversions
- for function pointer conversions
- allow
scopedto be added to areforinparameter, or to aref structparameter Allow addingscopedor removing[UnscopedRef]for override, interface implementation, or delegate conversion #62340 - allow
[UnscopedRef]to be removed from anoutparameter or from arefparameter of aref structAllow addingscopedor removing[UnscopedRef]for override, interface implementation, or delegate conversion #62340
-
scopedincluded in inferred delegate types:var f = (R x, scoped R y) => x; -
scopedparameters-
ref,in,out -
scoped thisin extension method -
params scoped
-
-
scopedlocals-
ref,ref readonly -
const -
foreachiteration variable -
usingvariable - deconstruction declaration
-
outdeclaration -
varandref var
-
- local with/without
scopedmodifier with scoped/unscoped initializer -
ScopedRefAttributechanges scoped default when targeting:-
reftoref structparameters -
outparameters
-
-
ScopedRefAttributedisallowed in source Report error if ScopedRefAttribute is used directly in source #62124 -
UnscopedRefAttribute:- member annotated with
[UnscopedRef]cannot implement an interface member Report error implementing unannotated interface member with[UnscopedRef]member #64508
- member annotated with
- updated escape rules
- ref-safe-to-escape for
reffields - ref reassignment
- ref-safe-to-escape and safe-to-escape for
scoped,scoped ref,ref scopedparameters and locals -
structthisis implicitlyscoped ref T -
outparameters are implicitlyscoped out -
scopedparameters affect argument contribution for ref-safe-to-escape and safe-to-escape of method invocation -
scopedparameters affect "method arguments must match" rule (arg "mixing")
- ref-safe-to-escape for
- warn when a parameter could be marked
scopedReport warning for unannotated parameters that could be markedscoped#64344 -
SymbolDisplay-
refqualifier and ref custom modifiers -
scopedandscoped reffor parameters and locals -
outparameters (should we show the implicitscoped?)
-
- document breaking changes:
- cannot return
outparameter by reference - rvalue from method invocation that returns a ref struct is safe-to-escape from ... the ref-safe-to-escape of all ref arguments
- cannot return
- Test when
scoped reforscoped incannot be passed as an argument to an ordinaryref/inparameter.- when the target method also returns
ref struct(RefFieldTests.ReturnRefFieldByValue) - when the target method also returns
ref/ref readonly(RefFieldTests.ReturnRefFieldByRef_03) - when the target method also has a
refparameter whose type isref struct(RefFieldTests.MethodArgumentsMustMatch_03)
- when the target method also returns
- auto-default: constructor must implicitly ref-assign a null-ref to
reffields which are not explicitlyref-assigned before all usages and returns. Auto-default ref fields with a null ref-assignment #63065 - cannot make an anonymous type with ref members
- disallow
void F([UnscopedRef] scoped ref int i) { }(RefFieldTests.UnscopedScoped) - allow updated escape rules with either
-langversion:11or RuntimeFeature.ByRefFields (i.e. NET 7) (RefFieldTests.UseUpdatedEscapeRules) -
requiredref fields (RefFieldTests.RequiredField_01, _02) - unskip test
RefFieldTests.InitRefField_UnsafeNullRef - unskip tests from RefFieldTests.vb
Public API
-
ScopedTypeSyntax -
IFieldSymbol.RefKindandRefCustomModifiers -
IParameterSymbol.ScopedKind -
ILocalSymbol.ScopedKind -
SymbolDisplay*OptionsUpdateSymbolDisplayto includescopedfor parameters and locals #63208 -
ScopedRefAttribute
Productivity
- classification for
scoped - formatting for
scoped - metadata as source for
scopedattributes (extracted to MetadataAsSource should show scoped modifiers #64906) - QuickInfo for
outparameters (should we show the implicitscoped?) (extracted to MetadataAsSource should show scoped modifiers #64906) - EE:
- Expression using
reffield - Expansion of instance with
reffield Test ref fields in the Expression Evaluator #62156
- Expression using
Open questions
- diagnostic for
scopedmodifier whenreforref structvalue cannot escape?Answer: don't give such a diagnostic, it will be inconvenient and disruptive to those who use scoped ref on refs which do not escape as a matter of style.static void F1<T>(scoped ref T t) { ... } // warning: scoped is unnecessary static void F2<T>(scoped Span<T> s) { ... } // warning: scoped is unnecessary
- diagnostic for
scoped outsinceoutparameters are implicitlyscoped? Answer: No, unless we hear further interest in such behavior. - should we emit the
[ScopedRef]attribute in metadata for anoutparameter? The spec says it's implicitlyscoped out. Answer: Don't emit ScopedRef when parameters are implicitly scoped.
Reactions are currently unavailable