-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Open
Labels
Area-CompilersTestTest failures in roslyn-CITest failures in roslyn-CITest-GapDescribes a specific feature or scenario that does not have test coverageDescribes a specific feature or scenario that does not have test coverage
Milestone
Description
- Specification checked in to
csharplang.
Feature List
Features
usingdeclaration Champion "Implicitly scoped using statement" (16.3, Core 3) csharplang#1174- pattern-based
usingforref structProposal: Allowusingstatement to structurally matchIDisposableon ref structs (16.3, Core 3) csharplang#1623
Code Examples
Using declarations
using var fileStream = new FileStream(@"temp\example.txt");
// vs.
using (var fileStream = new FileStream(@"temp\example.txt")) {
...
}
// Works for IAsyncDisposable as well.
await using var x = new AsyncDisposableType();Pattern based using for ref struct
ref struct S {
public void Dispose() { ... }
}
using var local = new S();Compiler Secnarios
- Ensure all features are tied to the C# 8.0 language version
- Goto and
usingdeclaration-
Goto can't jump over a
usingdeclaration unless it also jumps over the closing brace{ { goto target1; // error goto target2; // okay } using var fileStream = new FileStream(...); target1: ... } target2: ...
-
goto backwards over a
usingdeclaration must also cross the opening brace -
goto can jump around inside a block when it doesn't cross
usingdeclaration
-
- pattern based using on
ref struct- Follows the pattern based lookup specification
- Consider extension methods
- Consider generic methods where inference is possible
- Applies to enumerators inside a
foreachblock (both classic andawait foreach) - ensure a
ref structrespects the lifetime of the initializerref struct S { public Span<int> field; public void Dispose() { } } S M() { Span<int> span = stackalloc ... using S local = new S() { field = span; } return local; // error }
- Follows the pattern based lookup specification
-
usingdeclaration restrictions- prohibit
refandref readonlyin ausingdeclaration - test in conjunction with
const:using const ...(should be binding error),const using ...(parsing error?) - test without initializer:
using MyDisposable local; - test with non-disposable type
- test with missing well-known
IDisposabletype (see uses ofCompilation.MakeTypeMissing(WellKnownType)API) - test with missing well-known
IAsyncDisposabletype. - test
await usingdeclaration only legal inasyncmethod. - test can't use on a field or parameter
- test disallowed in case label (unless inside an explicit block)
- test in scripting
- test that
dynamicis allowed
- prohibit
-
usingdeclaration usage cases- test with
null/defaultvalue - test with lambdas or local functions that capture using variables and non-using variables
- variable is not assignable
- test can't use as
reforout. - possible to use a
structvariable asref readonlyorinstruct S : IDisposable { public void Dispose() { ... } } using S local = new S(); ref readonly rr1 = ref local; // okay ref rr2 = ref local; // error
- local functions and definite assignment
public void M() { // legal because there isn't a definite assignment issue Local(); using FileStream x; void Local() { x = null; // error is it's not assignable x.ToString(); } }
- order of dispose is reverse of declaration order
- multi-variable declarator dispose order
- multi-variable declarator dispose order in face of exception (all
finallyexecuted) - test inside an iterator
- test inside an async method
- test with
- Semantic Model
- Getting the awaiter info from a
usingdeclaration - Basic semantic information on the local from the API
- Getting the awaiter info from a
- Consider impact on F#
- ref struct with
Dispose()method should work if it returnsTaskorValueTask(task-like)- same for
DisposeAsync()
- same for
- test scripting (should disallow using-declaration, maybe some additional complications)
- check that using-declaration logic checks
AwaitUsingAndForeachAddsPendingBranchflag (context) - test ref struct with
Task? DisposeAsync()method inawait using(declaration or statement). Should produce a null warning - test async using-declaration in async-iterator method
- two async using-declarations with a
yield returnin between
- two async using-declarations with a
- test obsolete Dispose method on a ref struct in
usingor inforeach
Productivity
- Find all references (moved all FAR issues into FindAllReferences should handle
Disposereferenced inusingandforeachstatements #28228)- Finds
Disposemethod usage inusingdeclaration - Finds
Dispose/AsyncDisposemethod usage inforeachstatements
- Finds
- InlineVariable should not trigger for a
usingdeclaration variable (replaced by issue InlineVariable should not trigger for ausingdeclaration #35645) - Extract method should be disabled for blocks that have a
usingdeclaration (replaced by issue Extract Method should understandusingdeclarations #35646) - ENC
- Verify it's functional for pattern based dispose in
foreach - Using declarations going to be tricky. Mainly because adding “using” to a variable declaration implies
wrapping the containing scope in a finally block. We need to be careful where to place the sequence point that is
currently emitted for ‘}’ of such scope. EnC is especially concerned about all exception handling blocks and needs
to be aware of them.)
- Verify it's functional for pattern based dispose in
- test
MakeMethodAsyncon using-declaration. - verify sequence points and debugging experience
- Extras
- fixer to use the right kind of declaration (
await usingorusing) depending on the kind of disposable - refactoring to convert using-statement to using-declaration. (done)
- fixer to use the right kind of declaration (
Open LDM Issues
- Syntax for using var and IAsyncDisposable (
await using var x = ...)? - Should extension dispose be invoked for null values ( writing
x.Dispose()would call it,GetPinnableReference()for fixed doesn't) - Nullable-value types in using (should we fail if there isn't a lifted extension, or should we check null and call the underlying type if not)
- Handle the jump forward 'goto' case. Should we disallow labels in a block after a
using var(you can't jump into a using statement today as the scope is different)
Proposal: dotnet/csharplang#1703
Championed issue (with LDM history): dotnet/csharplang#1174
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Area-CompilersTestTest failures in roslyn-CITest failures in roslyn-CITest-GapDescribes a specific feature or scenario that does not have test coverageDescribes a specific feature or scenario that does not have test coverage