From b75c525448dd8f4d6153d59512e7b3ec31d5abb0 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Thu, 15 Sep 2022 11:45:22 -0700 Subject: [PATCH 1/4] 'scoped' should set escape scope to current block --- .../Symbols/Source/SourceLocalSymbol.cs | 9 +++-- .../Test/Semantic/Semantics/RefFieldTests.cs | 34 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs index 9327bc2dcc82b..bb731d4ce549e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs @@ -32,6 +32,7 @@ internal class SourceLocalSymbol : LocalSymbol private readonly RefKind _refKind; private readonly LocalDeclarationKind _declarationKind; private readonly DeclarationScope _scope; + private readonly uint _localScopeDepth; private TypeWithAnnotations.Boxed _type; @@ -89,6 +90,8 @@ private SourceLocalSymbol( // create this eagerly as it will always be needed for the EnsureSingleDefinition _locations = ImmutableArray.Create(identifierToken.GetLocation()); + _localScopeDepth = scopeBinder.LocalScopeDepth; + _refEscapeScope = this._refKind == RefKind.None ? scopeBinder.LocalScopeDepth : Binder.ExternalScope; // default to returnable, unless there is initializer @@ -129,7 +132,9 @@ internal sealed override uint RefEscapeScope { return _refEscapeScope; } - return Binder.TopLevelScope; + return _scope == DeclarationScope.RefScoped ? + _localScopeDepth : + Binder.TopLevelScope; } } @@ -143,7 +148,7 @@ internal sealed override uint ValEscapeScope return _valEscapeScope; } return _scope == DeclarationScope.ValueScoped ? - Binder.TopLevelScope : + _localScopeDepth : Binder.ExternalScope; } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs index af94c04f6948c..8a6e2c6f0c2d5 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs @@ -9115,6 +9115,40 @@ static void Test(ref int x) ); } + [WorkItem(64009, "https://github.com/dotnet/roslyn/issues/64009")] + [Fact] + public void LocalScope_09() + { + var source = +@"{ + scoped s1 = default; + scoped ref @scoped s2 = ref s1; +} +ref struct @scoped { } +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics(); + } + + [WorkItem(64009, "https://github.com/dotnet/roslyn/issues/64009")] + [Fact] + public void LocalScope_10() + { + var source = +@"{ + int i = 0; + S s1 = new S(ref i); + scoped S s2 = s1; +} +ref struct S +{ + public S(ref int i) { } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics(); + } + [Fact] public void LocalScopeAndInitializer_01() { From 165d1341a280e96011f5efa8703cc5120fb50e47 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Fri, 16 Sep 2022 13:00:24 -0700 Subject: [PATCH 2/4] More tests --- .../Test/Semantic/Semantics/RefFieldTests.cs | 69 ++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs index 8a6e2c6f0c2d5..f4b1d107afa6f 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs @@ -9130,7 +9130,6 @@ ref struct @scoped { } comp.VerifyDiagnostics(); } - [WorkItem(64009, "https://github.com/dotnet/roslyn/issues/64009")] [Fact] public void LocalScope_10() { @@ -9149,6 +9148,74 @@ public S(ref int i) { } comp.VerifyDiagnostics(); } + [Fact] + public void LocalScope_11() + { + var source = +@"class Program +{ + static void Main() + { + S s0 = default; + scoped ref S r0 = ref s0; + { + scoped ref S r1 = ref s0; + r0 = ref r1; // 1 + } + { + scoped ref S r2 = ref r0; + r0 = ref r2; // 2 + } + } +} +ref struct S { } +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (9,13): error CS8374: Cannot ref-assign 'r1' to 'r0' because 'r1' has a narrower escape scope than 'r0'. + // r0 = ref r1; // 1 + Diagnostic(ErrorCode.ERR_RefAssignNarrower, "r0 = ref r1").WithArguments("r0", "r1").WithLocation(9, 13), + // (13,13): error CS8374: Cannot ref-assign 'r2' to 'r0' because 'r2' has a narrower escape scope than 'r0'. + // r0 = ref r2; // 2 + Diagnostic(ErrorCode.ERR_RefAssignNarrower, "r0 = ref r2").WithArguments("r0", "r2").WithLocation(13, 13)); + } + + [Fact] + public void LocalScope_12() + { + var source = +@"class Program +{ + static void Main() + { + int i0 = 0; + S s0 = new S(ref i0); + { + int i1 = 1; + S s1 = new S(ref i1); + s0 = s1; // 1 + } + { + scoped S s2 = s0; + s0 = s2; // 2 + } + } +} +ref struct S +{ + public S(ref int i) { } +} +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (10,18): error CS8352: Cannot use variable 's1' in this context because it may expose referenced variables outside of their declaration scope + // s0 = s1; // 1 + Diagnostic(ErrorCode.ERR_EscapeVariable, "s1").WithArguments("s1").WithLocation(10, 18), + // (14,18): error CS8352: Cannot use variable 's2' in this context because it may expose referenced variables outside of their declaration scope + // s0 = s2; // 2 + Diagnostic(ErrorCode.ERR_EscapeVariable, "s2").WithArguments("s2").WithLocation(14, 18)); + } + [Fact] public void LocalScopeAndInitializer_01() { From 92f881b42f241fa3d62ec96da6d14839af34c67a Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Fri, 16 Sep 2022 17:13:24 -0700 Subject: [PATCH 3/4] PR feedback --- .../Portable/Symbols/Source/SourceLocalSymbol.cs | 7 ++----- .../Test/Semantic/Semantics/RefFieldTests.cs | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs index bb731d4ce549e..e6ca0c612d324 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs @@ -32,7 +32,6 @@ internal class SourceLocalSymbol : LocalSymbol private readonly RefKind _refKind; private readonly LocalDeclarationKind _declarationKind; private readonly DeclarationScope _scope; - private readonly uint _localScopeDepth; private TypeWithAnnotations.Boxed _type; @@ -90,8 +89,6 @@ private SourceLocalSymbol( // create this eagerly as it will always be needed for the EnsureSingleDefinition _locations = ImmutableArray.Create(identifierToken.GetLocation()); - _localScopeDepth = scopeBinder.LocalScopeDepth; - _refEscapeScope = this._refKind == RefKind.None ? scopeBinder.LocalScopeDepth : Binder.ExternalScope; // default to returnable, unless there is initializer @@ -133,7 +130,7 @@ internal sealed override uint RefEscapeScope return _refEscapeScope; } return _scope == DeclarationScope.RefScoped ? - _localScopeDepth : + _scopeBinder.LocalScopeDepth : Binder.TopLevelScope; } } @@ -148,7 +145,7 @@ internal sealed override uint ValEscapeScope return _valEscapeScope; } return _scope == DeclarationScope.ValueScoped ? - _localScopeDepth : + _scopeBinder.LocalScopeDepth : Binder.ExternalScope; } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs index f4b1d107afa6f..c6c4fdfca46a4 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs @@ -9162,10 +9162,18 @@ static void Main() scoped ref S r1 = ref s0; r0 = ref r1; // 1 } + { + ref S r2 = ref s0; + r0 = ref r2; + } { scoped ref S r2 = ref r0; r0 = ref r2; // 2 } + { + ref S r4 = ref r0; + r0 = ref r4; + } } } ref struct S { } @@ -9175,9 +9183,9 @@ ref struct S { } // (9,13): error CS8374: Cannot ref-assign 'r1' to 'r0' because 'r1' has a narrower escape scope than 'r0'. // r0 = ref r1; // 1 Diagnostic(ErrorCode.ERR_RefAssignNarrower, "r0 = ref r1").WithArguments("r0", "r1").WithLocation(9, 13), - // (13,13): error CS8374: Cannot ref-assign 'r2' to 'r0' because 'r2' has a narrower escape scope than 'r0'. + // (17,13): error CS8374: Cannot ref-assign 'r2' to 'r0' because 'r2' has a narrower escape scope than 'r0'. // r0 = ref r2; // 2 - Diagnostic(ErrorCode.ERR_RefAssignNarrower, "r0 = ref r2").WithArguments("r0", "r2").WithLocation(13, 13)); + Diagnostic(ErrorCode.ERR_RefAssignNarrower, "r0 = ref r2").WithArguments("r0", "r2").WithLocation(17, 13)); } [Fact] @@ -9199,6 +9207,10 @@ static void Main() scoped S s2 = s0; s0 = s2; // 2 } + { + S s2 = s0; + s0 = s2; + } } } ref struct S From 5c7a23984a17fc27e8369a1380b263e7fd6cd406 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Fri, 16 Sep 2022 17:16:52 -0700 Subject: [PATCH 4/4] Update local names --- .../Test/Semantic/Semantics/RefFieldTests.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs index c6c4fdfca46a4..d4e23cbe708ee 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs @@ -9162,14 +9162,14 @@ static void Main() scoped ref S r1 = ref s0; r0 = ref r1; // 1 } - { - ref S r2 = ref s0; - r0 = ref r2; - } { scoped ref S r2 = ref r0; r0 = ref r2; // 2 } + { + ref S r3 = ref s0; + r0 = ref r3; + } { ref S r4 = ref r0; r0 = ref r4; @@ -9183,9 +9183,9 @@ ref struct S { } // (9,13): error CS8374: Cannot ref-assign 'r1' to 'r0' because 'r1' has a narrower escape scope than 'r0'. // r0 = ref r1; // 1 Diagnostic(ErrorCode.ERR_RefAssignNarrower, "r0 = ref r1").WithArguments("r0", "r1").WithLocation(9, 13), - // (17,13): error CS8374: Cannot ref-assign 'r2' to 'r0' because 'r2' has a narrower escape scope than 'r0'. + // (13,13): error CS8374: Cannot ref-assign 'r2' to 'r0' because 'r2' has a narrower escape scope than 'r0'. // r0 = ref r2; // 2 - Diagnostic(ErrorCode.ERR_RefAssignNarrower, "r0 = ref r2").WithArguments("r0", "r2").WithLocation(17, 13)); + Diagnostic(ErrorCode.ERR_RefAssignNarrower, "r0 = ref r2").WithArguments("r0", "r2").WithLocation(13, 13)); } [Fact] @@ -9208,8 +9208,8 @@ static void Main() s0 = s2; // 2 } { - S s2 = s0; - s0 = s2; + S s3 = s0; + s0 = s3; } } }