提交 481e1a2e 编写于 作者: J Jared Parsons

Emit dynamic attribute in generated lambda methods

When emitting a lambda method that binds to a delegate with dynamic
parameters, emit the dynamic attribute in the corresponding parameter
locations. This facilitates debugging of the lambda as parameters will
properly light up as dynamic in expression evaluation.

close #4160
上级 44b2028f
......@@ -546,8 +546,7 @@ private void ReportUseSiteDiagnosticForDynamic(DiagnosticBag diagnostics, Identi
if (node.IsTypeInContextWhichNeedsDynamicAttribute())
{
if ((object)this.Compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_DynamicAttribute__ctor) == null ||
(object)this.Compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_DynamicAttribute__ctorTransformFlags) == null)
if (!Compilation.HasDynamicEmitAttributes())
{
// CONSIDER: Native compiler reports error CS1980 for each syntax node which binds to dynamic type, we do the same by reporting a diagnostic here.
// However, this means we generate multiple duplicate diagnostics, when a single one would suffice.
......
......@@ -2867,6 +2867,18 @@ public override IEnumerable<ISymbol> GetSymbolsWithName(Func<string, bool> predi
#endregion
/// <summary>
/// Returns if the compilation has all of the members necessary to emit metadata about
/// dynamic types.
/// </summary>
/// <returns></returns>
internal bool HasDynamicEmitAttributes()
{
return
(object)GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_DynamicAttribute__ctor) != null &&
(object)GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_DynamicAttribute__ctorTransformFlags) != null;
}
internal override AnalyzerDriver AnalyzerForLanguage(ImmutableArray<DiagnosticAnalyzer> analyzers, AnalyzerManager analyzerManager)
{
return new AnalyzerDriver<SyntaxKind>(analyzers, n => n.Kind(), analyzerManager);
......
......@@ -363,9 +363,7 @@ internal ErrorTypeSymbol CreateCycleInTypeForwarderErrorTypeSymbol(ref MetadataT
/// <summary>
/// Lookup declaration for predefined CorLib type in this Assembly.
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
/// <remarks></remarks>
/// <returns>The symbol for the pre-defined type or an error type if the type is not defined in the core library.</returns>
internal abstract NamedTypeSymbol GetDeclaredSpecialType(SpecialType type);
/// <summary>
......@@ -455,7 +453,7 @@ internal virtual bool GetGuidString(out string guidString)
/// <summary>
/// Gets the symbol for the pre-defined type from core library associated with this assembly.
/// </summary>
/// <returns>The symbol for the pre-defined type or null if the type is not defined in the core library.</returns>
/// <returns>The symbol for the pre-defined type or an error type if the type is not defined in the core library.</returns>
internal NamedTypeSymbol GetSpecialType(SpecialType type)
{
return CorLibrary.GetDeclaredSpecialType(type);
......
......@@ -149,6 +149,21 @@ public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences
}
}
internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder<SynthesizedAttributeData> attributes)
{
// Emit [Dynamic] on synthesized parameter symbols when the original parameter was dynamic
// in order to facilitate debugging. In the case the necessary attributes are missing
// this is a no-op. Emitting an error here, or when the original parameter was bound, would
// adversely effect the compilation or potentially change overload resolution.
var compilation = this.DeclaringCompilation;
if (Type.ContainsDynamic() &&
compilation.HasDynamicEmitAttributes() &&
compilation.GetSpecialType(SpecialType.System_Boolean).SpecialType == SpecialType.System_Boolean)
{
AddSynthesizedAttribute(ref attributes, compilation.SynthesizeDynamicAttribute(this.Type, this.CustomModifiers.Length, this.RefKind));
}
}
/// <summary>
/// For each parameter of a source method, construct a corresponding synthesized parameter
/// for a destination method.
......
......@@ -1182,5 +1182,61 @@ static IEnumerable<dynamic> Foo()
}
});
}
[Fact]
public void DynamicLambdaParameterChecksDynamic()
{
var source =
@"using System;
public class C
{
public static void Main()
{
Func<dynamic, object> f = x => x;
T(f(null));
}
public static void T(object o) { }
}";
// Make sure we emit without errors when dynamic attributes are not present.
CompileAndVerify(source, expectedSignatures: new[]
{
Signature(
"C+<>c",
"<Main>b__0_0",
".method assembly hidebysig instance System.Object <Main>b__0_0(System.Object x) cil managed")
});
}
[Fact]
[WorkItem(4160, "https://github.com/dotnet/roslyn/issues/4160")]
public void DynamicLambdaParametersEmitAsDynamic()
{
var source =
@"using System;
public class C
{
public static void Main()
{
Func<dynamic, object> f = x => x;
T(f(null));
}
public static void T(object o) { }
}";
CompileAndVerify(source, additionalRefs: new[] { CSharpRef, SystemCoreRef }, expectedSignatures: new[]
{
Signature(
"C+<>c",
"<Main>b__0_0",
".method assembly hidebysig instance System.Object <Main>b__0_0([System.Runtime.CompilerServices.DynamicAttribute()] System.Object x) cil managed")
});
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册