Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scoped should set ref escape scope to current block #64093

Merged
merged 4 commits into from
Sep 20, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ internal class SourceLocalSymbol : LocalSymbol
private readonly RefKind _refKind;
private readonly LocalDeclarationKind _declarationKind;
private readonly DeclarationScope _scope;
private readonly uint _localScopeDepth;

Copy link
Contributor

@AlekseyTs AlekseyTs Sep 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like we need to store this value, we have _scopeBinder readily available #Closed

private TypeWithAnnotations.Boxed _type;

Expand Down Expand Up @@ -89,6 +90,8 @@ private SourceLocalSymbol(
// create this eagerly as it will always be needed for the EnsureSingleDefinition
_locations = ImmutableArray.Create<Location>(identifierToken.GetLocation());

_localScopeDepth = scopeBinder.LocalScopeDepth;

_refEscapeScope = this._refKind == RefKind.None ?
scopeBinder.LocalScopeDepth :
Binder.ExternalScope; // default to returnable, unless there is initializer
Expand Down Expand Up @@ -129,7 +132,9 @@ internal sealed override uint RefEscapeScope
{
return _refEscapeScope;
}
return Binder.TopLevelScope;
return _scope == DeclarationScope.RefScoped ?
_localScopeDepth :
Binder.TopLevelScope;
}
}

Expand All @@ -143,7 +148,7 @@ internal sealed override uint ValEscapeScope
return _valEscapeScope;
}
return _scope == DeclarationScope.ValueScoped ?
Binder.TopLevelScope :
_localScopeDepth :
Binder.ExternalScope;
}
}
Expand Down
101 changes: 101 additions & 0 deletions src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9115,6 +9115,107 @@ 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();
}

[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 LocalScope_11()
RikkiGibson marked this conversation as resolved.
Show resolved Hide resolved
{
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()
{
Expand Down