未验证 提交 cabc9bb6 编写于 作者: F Fred Silberberg 提交者: GitHub

Merge pull request #38251 from svick/static-local-delegate

Allow static local functions to convert static functions to delegates
......@@ -15,12 +15,14 @@ Each entry should include a short description of the break, followed by either a
void M()
{
void Local() {}
static void StaticLocal()
{
Local();
}
}
```
Such code will produce an error in version 16.4.
3. https://github.com/dotnet/roslyn/issues/35684 In C# `7.1` the resolution of a binary operator with a `default` literal could result in using an object equality and giving the literal a type `object`.
......@@ -30,3 +32,19 @@ Each entry should include a short description of the break, followed by either a
4. In C# `7.1`, `default as TClass` and `using (default)` were allowed. In *Visual Studio 2019 version 16.4* those scenarios will now produce errors.
5. https://github.com/dotnet/roslyn/issues/38240 Visual Studio 2019 version 16.3 incorrectly allowed for a `static` local function to create a delegate using a delegate creation expression whose target requires capturing state. For example:
```c#
void M()
{
object local;
static void F()
{
_ = new Func<int>(local.GetHashCode);
}
}
```
Such code will produce an error in version 16.4.
\ No newline at end of file
......@@ -586,7 +586,8 @@ public override BoundNode VisitConversion(BoundConversion node)
switch (node.ConversionKind)
{
case ConversionKind.MethodGroup:
VisitMethodGroup((BoundMethodGroup)node.Operand, parentIsConversion: true);
CheckMethodGroup((BoundMethodGroup)node.Operand, node.Conversion.Method, parentIsConversion: true);
return node;
case ConversionKind.AnonymousFunction:
......@@ -632,9 +633,9 @@ public override BoundNode VisitDelegateCreationExpression(BoundDelegateCreationE
{
this.Visit(node.Argument);
}
else if (_inExpressionLambda && node.MethodOpt?.MethodKind == MethodKind.LocalFunction)
else
{
Error(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, node);
CheckMethodGroup((BoundMethodGroup)node.Argument, node.MethodOpt, parentIsConversion: true);
}
return null;
......@@ -642,10 +643,11 @@ public override BoundNode VisitDelegateCreationExpression(BoundDelegateCreationE
public override BoundNode VisitMethodGroup(BoundMethodGroup node)
{
return VisitMethodGroup(node, parentIsConversion: false);
CheckMethodGroup(node, method: null, parentIsConversion: false);
return null;
}
private BoundNode VisitMethodGroup(BoundMethodGroup node, bool parentIsConversion)
private void CheckMethodGroup(BoundMethodGroup node, MethodSymbol method, bool parentIsConversion)
{
// Formerly reported ERR_MemGroupInExpressionTree when this occurred, but the expanded
// ERR_LambdaInIsAs makes this impossible (since the node will always be wrapped in
......@@ -658,7 +660,16 @@ private BoundNode VisitMethodGroup(BoundMethodGroup node, bool parentIsConversio
}
CheckReceiverIfField(node.ReceiverOpt);
return base.VisitMethodGroup(node);
if (method is LocalFunctionSymbol)
{
CheckReferenceToVariable(node, method);
}
if (method == null || method.RequiresInstanceReceiver)
{
Visit(node.ReceiverOpt);
}
}
public override BoundNode VisitNameOfOperator(BoundNameOfOperator node)
......
......@@ -1691,7 +1691,7 @@ Expression<Func<T>> Local<T>(Expression<Func<T>> f)
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, "Id").WithLocation(17, 51),
// (18,35): error CS8096: An expression tree may not contain a reference to a local function
// Console.Write(Local(() => new Func<int, int>(Id)));
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, "new Func<int, int>(Id)").WithLocation(18, 35)
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, "Id").WithLocation(18, 54)
);
}
......@@ -4923,5 +4923,139 @@ static void F3()
// F1();
Diagnostic(ErrorCode.ERR_StaticLocalFunctionCannotCaptureVariable, "F1()").WithArguments("F1").WithLocation(11, 13));
}
[Fact, WorkItem(38240, "https://github.com/dotnet/roslyn/issues/38240")]
public void StaticLocalFunctionLocalFunctionDelegateReference()
{
var source =
@"#pragma warning disable 8321
using System;
class C
{
static void M()
{
void F1() {}
static void F2()
{
Action a = F1;
_ = new Action(F1);
}
}
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (11,24): error CS8421: A static local function cannot contain a reference to 'F1'.
// Action a = F1;
Diagnostic(ErrorCode.ERR_StaticLocalFunctionCannotCaptureVariable, "F1").WithArguments("F1").WithLocation(11, 24),
// (12,28): error CS8421: A static local function cannot contain a reference to 'F1'.
// _ = new Action(F1);
Diagnostic(ErrorCode.ERR_StaticLocalFunctionCannotCaptureVariable, "F1").WithArguments("F1").WithLocation(12, 28));
}
[Fact, WorkItem(38240, "https://github.com/dotnet/roslyn/issues/38240")]
public void StaticLocalFunctionStaticFunctionsDelegateReference()
{
var source =
@"#pragma warning disable 8321
using System;
class C
{
static void M()
{
static void F1() {}
static void F2()
{
Action m = M;
Action f1 = F1;
_ = new Action(M);
_ = new Action(F1);
}
}
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
}
[Fact, WorkItem(38240, "https://github.com/dotnet/roslyn/issues/38240")]
public void StaticLocalFunctionThisAndBaseDelegateReference()
{
var source =
@"#pragma warning disable 8321
using System;
class B
{
public virtual void M() {}
}
class C : B
{
public override void M()
{
static void F()
{
Action a1 = base.M;
Action a2 = this.M;
Action a3 = M;
_ = new Action(base.M);
_ = new Action(this.M);
_ = new Action(M);
}
}
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (14,25): error CS8422: A static local function cannot contain a reference to 'this' or 'base'.
// Action a1 = base.M;
Diagnostic(ErrorCode.ERR_StaticLocalFunctionCannotCaptureThis, "base").WithLocation(14, 25),
// (15,25): error CS8422: A static local function cannot contain a reference to 'this' or 'base'.
// Action a2 = this.M;
Diagnostic(ErrorCode.ERR_StaticLocalFunctionCannotCaptureThis, "this").WithLocation(15, 25),
// (16,25): error CS8422: A static local function cannot contain a reference to 'this' or 'base'.
// Action a3 = M;
Diagnostic(ErrorCode.ERR_StaticLocalFunctionCannotCaptureThis, "M").WithLocation(16, 25),
// (17,28): error CS8422: A static local function cannot contain a reference to 'this' or 'base'.
// _ = new Action(base.M);
Diagnostic(ErrorCode.ERR_StaticLocalFunctionCannotCaptureThis, "base").WithLocation(17, 28),
// (18,28): error CS8422: A static local function cannot contain a reference to 'this' or 'base'.
// _ = new Action(this.M);
Diagnostic(ErrorCode.ERR_StaticLocalFunctionCannotCaptureThis, "this").WithLocation(18, 28),
// (19,28): error CS8422: A static local function cannot contain a reference to 'this' or 'base'.
// _ = new Action(M);
Diagnostic(ErrorCode.ERR_StaticLocalFunctionCannotCaptureThis, "M").WithLocation(19, 28));
}
[Fact, WorkItem(38240, "https://github.com/dotnet/roslyn/issues/38240")]
public void StaticLocalFunctionDelegateReferenceWithReceiver()
{
var source =
@"#pragma warning disable 649
#pragma warning disable 8321
using System;
class C
{
object f;
void M()
{
object l;
static void F1()
{
_ = new Func<int>(f.GetHashCode);
_ = new Func<int>(l.GetHashCode);
}
}
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (14,31): error CS8422: A static local function cannot contain a reference to 'this' or 'base'.
// _ = new Func<int>(f.GetHashCode);
Diagnostic(ErrorCode.ERR_StaticLocalFunctionCannotCaptureThis, "f").WithLocation(14, 31),
// (15,31): error CS8421: A static local function cannot contain a reference to 'l'.
// _ = new Func<int>(l.GetHashCode);
Diagnostic(ErrorCode.ERR_StaticLocalFunctionCannotCaptureVariable, "l").WithArguments("l").WithLocation(15, 31));
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册