Skip to content

Commit c0c896c

Browse files
authored
scoped should set ref escape scope to current block (#64093)
1 parent cd5e689 commit c0c896c

2 files changed

Lines changed: 117 additions & 2 deletions

File tree

src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ internal sealed override uint RefEscapeScope
129129
{
130130
return _refEscapeScope;
131131
}
132-
return Binder.TopLevelScope;
132+
return _scope == DeclarationScope.RefScoped ?
133+
_scopeBinder.LocalScopeDepth :
134+
Binder.TopLevelScope;
133135
}
134136
}
135137

@@ -143,7 +145,7 @@ internal sealed override uint ValEscapeScope
143145
return _valEscapeScope;
144146
}
145147
return _scope == DeclarationScope.ValueScoped ?
146-
Binder.TopLevelScope :
148+
_scopeBinder.LocalScopeDepth :
147149
Binder.ExternalScope;
148150
}
149151
}

src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9273,6 +9273,119 @@ static void Test(ref int x)
92739273
);
92749274
}
92759275

9276+
[WorkItem(64009, "https://github.com/dotnet/roslyn/issues/64009")]
9277+
[Fact]
9278+
public void LocalScope_09()
9279+
{
9280+
var source =
9281+
@"{
9282+
scoped s1 = default;
9283+
scoped ref @scoped s2 = ref s1;
9284+
}
9285+
ref struct @scoped { }
9286+
";
9287+
var comp = CreateCompilation(source);
9288+
comp.VerifyDiagnostics();
9289+
}
9290+
9291+
[Fact]
9292+
public void LocalScope_10()
9293+
{
9294+
var source =
9295+
@"{
9296+
int i = 0;
9297+
S s1 = new S(ref i);
9298+
scoped S s2 = s1;
9299+
}
9300+
ref struct S
9301+
{
9302+
public S(ref int i) { }
9303+
}
9304+
";
9305+
var comp = CreateCompilation(source);
9306+
comp.VerifyDiagnostics();
9307+
}
9308+
9309+
[Fact]
9310+
public void LocalScope_11()
9311+
{
9312+
var source =
9313+
@"class Program
9314+
{
9315+
static void Main()
9316+
{
9317+
S s0 = default;
9318+
scoped ref S r0 = ref s0;
9319+
{
9320+
scoped ref S r1 = ref s0;
9321+
r0 = ref r1; // 1
9322+
}
9323+
{
9324+
scoped ref S r2 = ref r0;
9325+
r0 = ref r2; // 2
9326+
}
9327+
{
9328+
ref S r3 = ref s0;
9329+
r0 = ref r3;
9330+
}
9331+
{
9332+
ref S r4 = ref r0;
9333+
r0 = ref r4;
9334+
}
9335+
}
9336+
}
9337+
ref struct S { }
9338+
";
9339+
var comp = CreateCompilation(source);
9340+
comp.VerifyDiagnostics(
9341+
// (9,13): error CS8374: Cannot ref-assign 'r1' to 'r0' because 'r1' has a narrower escape scope than 'r0'.
9342+
// r0 = ref r1; // 1
9343+
Diagnostic(ErrorCode.ERR_RefAssignNarrower, "r0 = ref r1").WithArguments("r0", "r1").WithLocation(9, 13),
9344+
// (13,13): error CS8374: Cannot ref-assign 'r2' to 'r0' because 'r2' has a narrower escape scope than 'r0'.
9345+
// r0 = ref r2; // 2
9346+
Diagnostic(ErrorCode.ERR_RefAssignNarrower, "r0 = ref r2").WithArguments("r0", "r2").WithLocation(13, 13));
9347+
}
9348+
9349+
[Fact]
9350+
public void LocalScope_12()
9351+
{
9352+
var source =
9353+
@"class Program
9354+
{
9355+
static void Main()
9356+
{
9357+
int i0 = 0;
9358+
S s0 = new S(ref i0);
9359+
{
9360+
int i1 = 1;
9361+
S s1 = new S(ref i1);
9362+
s0 = s1; // 1
9363+
}
9364+
{
9365+
scoped S s2 = s0;
9366+
s0 = s2; // 2
9367+
}
9368+
{
9369+
S s3 = s0;
9370+
s0 = s3;
9371+
}
9372+
}
9373+
}
9374+
ref struct S
9375+
{
9376+
public S(ref int i) { }
9377+
}
9378+
";
9379+
var comp = CreateCompilation(source);
9380+
comp.VerifyDiagnostics(
9381+
// (10,18): error CS8352: Cannot use variable 's1' in this context because it may expose referenced variables outside of their declaration scope
9382+
// s0 = s1; // 1
9383+
Diagnostic(ErrorCode.ERR_EscapeVariable, "s1").WithArguments("s1").WithLocation(10, 18),
9384+
// (14,18): error CS8352: Cannot use variable 's2' in this context because it may expose referenced variables outside of their declaration scope
9385+
// s0 = s2; // 2
9386+
Diagnostic(ErrorCode.ERR_EscapeVariable, "s2").WithArguments("s2").WithLocation(14, 18));
9387+
}
9388+
92769389
[Fact]
92779390
public void LocalScopeAndInitializer_01()
92789391
{

0 commit comments

Comments
 (0)