未验证 提交 e445f1e6 编写于 作者: C Charles Stoner 提交者: GitHub

Ensure synthesized closure method is static for static local function (#38147)

上级 9b28c90f
......@@ -425,6 +425,7 @@ private void SynthesizeLoweredFunctionMethods()
closureOrdinal = LambdaDebugInfo.ThisOnlyClosureOrdinal;
}
else if (closure.CapturedEnvironments.Count == 0 &&
originalMethod.MethodKind == MethodKind.LambdaMethod &&
_analysis.MethodsConvertedToDelegates.Contains(originalMethod))
{
translatedLambdaContainer = containerAsFrame = GetStaticFrame(Diagnostics, syntax);
......@@ -992,6 +993,16 @@ private ImmutableArray<TypeWithAnnotations> SubstituteTypeArguments(ImmutableArr
constructedFrame = translatedLambdaContainer;
}
synthesizedMethod = synthesizedMethod.AsMember(constructedFrame);
if (synthesizedMethod.IsGenericMethod)
{
synthesizedMethod = synthesizedMethod.Construct(realTypeArguments);
}
else
{
Debug.Assert(realTypeArguments.Length == 0);
}
// for instance lambdas, receiver is the frame
// for static lambdas, get the singleton receiver
if (closureKind == ClosureKind.Singleton)
......@@ -1001,22 +1012,12 @@ private ImmutableArray<TypeWithAnnotations> SubstituteTypeArguments(ImmutableArr
}
else if (closureKind == ClosureKind.Static)
{
receiver = null;
receiver = new BoundTypeExpression(syntax, null, synthesizedMethod.ContainingType);
}
else // ThisOnly and General
{
receiver = FrameOfType(syntax, constructedFrame);
}
synthesizedMethod = synthesizedMethod.AsMember(constructedFrame);
if (synthesizedMethod.IsGenericMethod)
{
synthesizedMethod = synthesizedMethod.Construct(realTypeArguments);
}
else
{
Debug.Assert(realTypeArguments.Length == 0);
}
}
public override BoundNode VisitCall(BoundCall node)
......
......@@ -2571,9 +2571,8 @@ T Goo<T>(T x)
var verify = VerifyOutputInMain(source, "2", "System");
var goo = verify.FindLocalFunction("Goo");
var program = verify.Compilation.GetTypeByMetadataName("Program");
Assert.False(goo.IsStatic);
Assert.Equal("<>c", goo.ContainingType.Name);
Assert.Equal(program, goo.ContainingType.ContainingType);
Assert.True(goo.IsStatic);
Assert.Equal(program, goo.ContainingType);
}
[Fact]
......
......@@ -1423,15 +1423,14 @@ static object F()
// new lambda "<F>b__0#1" has been added:
diff1.VerifySynthesizedMembers(
"C: {<>c}",
"C.<>c: {<F>g__f|0#1}");
"C: {<F>g__f|0#1}");
// added:
diff1.VerifyIL("C.<>c.<F>g__f|0#1(int)", @"
diff1.VerifyIL("C.<F>g__f|0#1(int)", @"
{
// Code size 4 (0x4)
.maxstack 2
IL_0000: ldarg.1
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: add
IL_0003: ret
......@@ -1443,15 +1442,14 @@ .maxstack 2
ImmutableArray.Create(new SemanticEdit(SemanticEditKind.Update, f1, f2, GetSyntaxMapFromMarkers(source1, source2), preserveLocalVariables: true)));
diff2.VerifySynthesizedMembers(
"C: {<>c}",
"C.<>c: {<F>g__f|0#1}");
"C: {<F>g__f|0#1}");
// updated:
diff2.VerifyIL("C.<>c.<F>g__f|0#1(int)", @"
diff2.VerifyIL("C.<F>g__f|0#1(int)", @"
{
// Code size 4 (0x4)
.maxstack 2
IL_0000: ldarg.1
IL_0000: ldarg.0
IL_0001: ldc.i4.2
IL_0002: add
IL_0003: ret
......@@ -1822,15 +1820,14 @@ static object F()
var reader1 = md1.Reader;
diff1.VerifySynthesizedMembers(
"C: {<>c}",
"C.<>c: {<F>g__f1|1_0, <F>g__f2|1_1#1}");
"C: {<F>g__f1|1_0, <F>g__f2|1_1#1}");
// updated:
diff1.VerifyIL("C.<>c.<F>g__f1|1_0(int)", @"
diff1.VerifyIL("C.<F>g__f1|1_0(int)", @"
{
// Code size 4 (0x4)
.maxstack 2
IL_0000: ldarg.1
IL_0000: ldarg.0
IL_0001: ldc.i4.2
IL_0002: add
IL_0003: ret
......@@ -1838,11 +1835,11 @@ .maxstack 2
");
// added:
diff1.VerifyIL("C.<>c.<F>g__f2|1_1#1(int)", @"
diff1.VerifyIL("C.<F>g__f2|1_1#1(int)", @"
{
// Code size 5 (0x5)
.maxstack 2
IL_0000: ldarg.1
IL_0000: ldarg.0
IL_0001: ldc.i4.s 20
IL_0003: add
IL_0004: ret
......@@ -1854,26 +1851,25 @@ .maxstack 2
ImmutableArray.Create(new SemanticEdit(SemanticEditKind.Update, f1, f2, GetSyntaxMapFromMarkers(source1, source2), preserveLocalVariables: true)));
diff2.VerifySynthesizedMembers(
"C.<>c: {<F>g__f1|1_0, <F>g__f2|1_1#1, <F>g__f3|1_2#2}",
"C: {<>c}");
"C: {<F>g__f1|1_0, <F>g__f2|1_1#1, <F>g__f3|1_2#2}");
// updated:
diff2.VerifyIL("C.<>c.<F>g__f1|1_0(int)", @"
diff2.VerifyIL("C.<F>g__f1|1_0(int)", @"
{
// Code size 4 (0x4)
.maxstack 2
IL_0000: ldarg.1
IL_0000: ldarg.0
IL_0001: ldc.i4.3
IL_0002: add
IL_0003: ret
}
");
// updated:
diff2.VerifyIL("C.<>c.<F>g__f2|1_1#1(int)", @"
diff2.VerifyIL("C.<F>g__f2|1_1#1(int)", @"
{
// Code size 5 (0x5)
.maxstack 2
IL_0000: ldarg.1
IL_0000: ldarg.0
IL_0001: ldc.i4.s 30
IL_0003: add
IL_0004: ret
......@@ -1881,11 +1877,11 @@ .maxstack 2
");
// added:
diff2.VerifyIL("C.<>c.<F>g__f3|1_2#2(int)", @"
diff2.VerifyIL("C.<F>g__f3|1_2#2(int)", @"
{
// Code size 8 (0x8)
.maxstack 2
IL_0000: ldarg.1
IL_0000: ldarg.0
IL_0001: ldc.i4 0x300
IL_0006: add
IL_0007: ret
......@@ -1897,26 +1893,25 @@ .maxstack 2
ImmutableArray.Create(new SemanticEdit(SemanticEditKind.Update, f2, f3, GetSyntaxMapFromMarkers(source2, source3), preserveLocalVariables: true)));
diff3.VerifySynthesizedMembers(
"C: {<>c}",
"C.<>c: {<F>g__f1|1_0, <F>g__f2|1_1#1, <F>g__f3|1_2#2}");
"C: {<F>g__f1|1_0, <F>g__f2|1_1#1, <F>g__f3|1_2#2}");
// updated:
diff3.VerifyIL("C.<>c.<F>g__f1|1_0(int)", @"
diff3.VerifyIL("C.<F>g__f1|1_0(int)", @"
{
// Code size 4 (0x4)
.maxstack 2
IL_0000: ldarg.1
IL_0000: ldarg.0
IL_0001: ldc.i4.4
IL_0002: add
IL_0003: ret
}
");
// updated:
diff3.VerifyIL("C.<>c.<F>g__f2|1_1#1(int)", @"
diff3.VerifyIL("C.<F>g__f2|1_1#1(int)", @"
{
// Code size 5 (0x5)
.maxstack 2
IL_0000: ldarg.1
IL_0000: ldarg.0
IL_0001: ldc.i4.s 40
IL_0003: add
IL_0004: ret
......@@ -1924,11 +1919,11 @@ .maxstack 2
");
// updated:
diff3.VerifyIL("C.<>c.<F>g__f3|1_2#2(int)", @"
diff3.VerifyIL("C.<F>g__f3|1_2#2(int)", @"
{
// Code size 8 (0x8)
.maxstack 2
IL_0000: ldarg.1
IL_0000: ldarg.0
IL_0001: ldc.i4 0x400
IL_0006: add
IL_0007: ret
......
......@@ -5057,5 +5057,45 @@ static void F1()
// _ = new Func<int>(l.GetHashCode);
Diagnostic(ErrorCode.ERR_StaticLocalFunctionCannotCaptureVariable, "l").WithArguments("l").WithLocation(15, 31));
}
[Fact]
[WorkItem(38143, "https://github.com/dotnet/roslyn/issues/38143")]
public void EmittedAsStatic_01()
{
var source =
@"class Program
{
static void M()
{
static void local() { }
System.Action action = local;
}
}";
CompileAndVerify(source, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: m =>
{
var method = (MethodSymbol)m.GlobalNamespace.GetMember("Program.<M>g__local|0_0");
Assert.True(method.IsStatic);
});
}
[Fact]
[WorkItem(38143, "https://github.com/dotnet/roslyn/issues/38143")]
public void EmittedAsStatic_02()
{
var source =
@"class Program
{
static void M<T>()
{
static void local(T t) { }
System.Action<T> action = local;
}
}";
CompileAndVerify(source, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: m =>
{
var method = (MethodSymbol)m.GlobalNamespace.GetMember("Program.<M>g__local|0_0");
Assert.True(method.IsStatic);
});
}
}
}
using System.Linq;
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册