未验证 提交 03b8d09b 编写于 作者: Y Yair Halberstadt 提交者: GitHub

fix ref returns in expression bodied local functions (#42333)

 Fix #42259 caused by use of incorrect binder when checking ref return type.
上级 8e477d8a
...@@ -3163,14 +3163,20 @@ private static bool IsValidExpressionBody(SyntaxNode expressionSyntax, BoundExpr ...@@ -3163,14 +3163,20 @@ private static bool IsValidExpressionBody(SyntaxNode expressionSyntax, BoundExpr
Binder bodyBinder = this.GetBinder(expressionBody); Binder bodyBinder = this.GetBinder(expressionBody);
Debug.Assert(bodyBinder != null); Debug.Assert(bodyBinder != null);
RefKind refKind = RefKind.None; return bindExpressionBodyAsBlockInternal(expressionBody, bodyBinder, diagnostics);
// Use static local function to prevent accidentally calling instance methods on `this` instead of `bodyBinder`
static BoundBlock bindExpressionBodyAsBlockInternal(ArrowExpressionClauseSyntax expressionBody, Binder bodyBinder, DiagnosticBag diagnostics)
{
RefKind refKind;
ExpressionSyntax expressionSyntax = expressionBody.Expression.CheckAndUnwrapRefExpression(diagnostics, out refKind); ExpressionSyntax expressionSyntax = expressionBody.Expression.CheckAndUnwrapRefExpression(diagnostics, out refKind);
BindValueKind requiredValueKind = GetRequiredReturnValueKind(refKind); BindValueKind requiredValueKind = bodyBinder.GetRequiredReturnValueKind(refKind);
BoundExpression expression = bodyBinder.BindValue(expressionSyntax, diagnostics, requiredValueKind); BoundExpression expression = bodyBinder.BindValue(expressionSyntax, diagnostics, requiredValueKind);
expression = ValidateEscape(expression, Binder.ExternalScope, refKind != RefKind.None, diagnostics); expression = bodyBinder.ValidateEscape(expression, Binder.ExternalScope, refKind != RefKind.None, diagnostics);
return bodyBinder.CreateBlockFromExpression(expressionBody, bodyBinder.GetDeclaredLocalsForScope(expressionBody), refKind, expression, expressionSyntax, diagnostics); return bodyBinder.CreateBlockFromExpression(expressionBody, bodyBinder.GetDeclaredLocalsForScope(expressionBody), refKind, expression, expressionSyntax, diagnostics);
} }
}
/// <summary> /// <summary>
/// Binds a lambda with expression e as either { return e;} or { e; }. /// Binds a lambda with expression e as either { return e;} or { e; }.
......
...@@ -313,6 +313,44 @@ class C ...@@ -313,6 +313,44 @@ class C
Diagnostic(ErrorCode.ERR_AssgReadonly, "_ro").WithLocation(15, 47)); Diagnostic(ErrorCode.ERR_AssgReadonly, "_ro").WithLocation(15, 47));
} }
[Fact, WorkItem(42259, "https://github.com/dotnet/roslyn/issues/42259")]
public void RefReturnLocalFunction()
{
var source = @"
#pragma warning disable CS8321
class C {
static void M(){
ref int M1(in int i) => ref i;
ref int M2(in int i) { return ref i; }
ref readonly int M3(in int i) => ref i;
ref readonly int M4(in int i) { return ref i; }
}
}";
CreateCompilation(source).VerifyDiagnostics(
// (5,37): error CS8333: Cannot return variable 'in int' by writable reference because it is a readonly variable
// ref int M1(in int i) => ref i;
Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "i").WithArguments("variable", "in int").WithLocation(5, 37),
// (6,43): error CS8333: Cannot return variable 'in int' by writable reference because it is a readonly variable
// ref int M2(in int i) { return ref i; }
Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "i").WithArguments("variable", "in int").WithLocation(6, 43)
);
}
[Fact, WorkItem(42259, "https://github.com/dotnet/roslyn/issues/42259")]
public void RefReadonlyReturnLocalFunction()
{
var source = @"
#pragma warning disable CS8321
class C {
ref int M(){
throw new System.Exception();
ref readonly int M1(in int i) => ref i;
ref readonly int M2(in int i) { return ref i; }
}
}";
CreateCompilation(source).VerifyDiagnostics();
}
[Fact] [Fact]
public void ReadonlyFieldRefReassign() public void ReadonlyFieldRefReassign()
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册