Skip to content

CompilerServices.Closure redirect seems to be missing #119188

@kg

Description

@kg

Description

I have an application built using .NET 4.8 that makes extensive use of LINQ CompileToMethod to precompile lots of scripts to managed binaries. This works great on .NET 4.8 and almost works right on .NET 9 using a runtimeconfig + dotnet exec to run the application.

I'm using the runtimeconfig trick to identify .NET core compatibility issues before trying to roll the whole application forward, and considering using the runtimeconfig trick to deploy the application itself. (Rolling it forward as-is is difficult because its script compiler relies on LINQ CompileToMethod and AssemblyBuilder.Save.)

The problem appears to be a missing redirect for CompilerServices.Closure and maybe also StrongBox`1. The rest of the application seems to work fine.

Reproduction Steps

  1. Compile a LINQ expression containing a closure using LINQ CompileToMethod on .NET 4.8
  2. Invoke the compiled method on modern .NET

I can share a build of the application that will repro the issue, but for licensing reasons (middleware fees not yet paid) I can't distribute it publicly yet. Just email me.

An example DLL containing problematic references to Closure is here:
action.zip
It was generated using the BCL's LINQ CompileToMethod and AssemblyBuilder.Save.

Expected behavior

System.Runtime.CompilerServices.Closure should resolve to System.Linq.Expressions.dll since that seems to be where it lives now.

Actual behavior

>  ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
>  ---> System.TypeLoadException: Could not load type 'System.Runtime.CompilerServices.Closure' from assembly 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
>    at System.Signature.GetSignature(Void* pCorSig, Int32 cCorSig, RuntimeFieldHandleInternal fieldHandle, IRuntimeMethodInfo methodHandle, RuntimeType declaringType)
>    at System.Reflection.RuntimeMethodInfo.<get_Signature>g__LazyCreateSignature|25_0()
>    at System.Reflection.RuntimeMethodInfo.get_ReturnType()

It appears that there's no redirect/forwarding from System.Core to Closure's new home.

Regression?

It worked in .NET Framework, but I don't think this is a regression compared to a previous version of .NET Core

Known Workarounds

  1. Use .NET Framework
  2. Patch the DLLs, maybe?

Configuration

.NET 9.0.6 on Windows 11 x64

Other information

Some sample IL of a method that fails:

.method public static 
	class [mscorlib]System.Threading.Tasks.Task l40c5_decl (
		class [HeavenLens]HeavenLens.Combat.ActionScriptContext context
	) cil managed 
{
	// Method begins at RVA 0x153dc
	// Header size: 12
	// Code size: 95 (0x5f)
	.maxstack 6
	.locals init (
		[0] object[]
	)

	IL_0000: ldc.i4.1
	IL_0001: newarr [mscorlib]System.Object
	IL_0006: dup
	IL_0007: ldc.i4.0
	IL_0008: ldarg.0
	IL_0009: newobj instance void class [System.Core]System.Runtime.CompilerServices.StrongBox`1<class [HeavenLens]HeavenLens.Combat.ActionScriptContext>::.ctor(!0)
	IL_000e: stelem.ref
	IL_000f: stloc.0
	IL_0010: nop
	IL_0011: nop
	IL_0012: ldloc.0
	IL_0013: ldc.i4.0
	IL_0014: ldelem.ref
	IL_0015: castclass class [System.Core]System.Runtime.CompilerServices.StrongBox`1<class [HeavenLens]HeavenLens.Combat.ActionScriptContext>
	IL_001a: ldfld !0 class [System.Core]System.Runtime.CompilerServices.StrongBox`1<class [HeavenLens]HeavenLens.Combat.ActionScriptContext>::Value
	IL_001f: ldstr "Power"
	IL_0024: nop
	IL_0025: ldloc.0
	IL_0026: ldc.i4.0
	IL_0027: ldelem.ref
	IL_0028: castclass class [System.Core]System.Runtime.CompilerServices.StrongBox`1<class [HeavenLens]HeavenLens.Combat.ActionScriptContext>
	IL_002d: ldfld !0 class [System.Core]System.Runtime.CompilerServices.StrongBox`1<class [HeavenLens]HeavenLens.Combat.ActionScriptContext>::Value
	IL_0032: castclass class [HeavenLens]HeavenLens.HLBaseScriptContext`1<class [HeavenLens]HeavenLens.Combat.ActionScriptContext>
	IL_0037: ldnull
	IL_0038: ldloc.0
	IL_0039: newobj instance void [System.Core]System.Runtime.CompilerServices.Closure::.ctor(object[], object[])
	IL_003e: ldftn float64 attack_gun.Statements::'<ExpressionCompilerImplementationDetails>{163}lambda_method'(class [System.Core]System.Runtime.CompilerServices.Closure)
	IL_0044: newobj instance void class [mscorlib]System.Func`1<float64>::.ctor(object, native int)
	IL_0049: newobj instance void valuetype [HeavenLens.Data]HeavenLens.Scripts.ValueOrClosure`1<float64>::.ctor(class [mscorlib]System.Func`1<!0>)
	IL_004e: ldstr "Power"
	IL_0053: callvirt instance class [HeavenLens]HeavenLens.RuntimeExpression class [HeavenLens]HeavenLens.HLBaseScriptContext`1<class [HeavenLens]HeavenLens.Combat.ActionScriptContext>::Expr(valuetype [HeavenLens.Data]HeavenLens.Scripts.ValueOrClosure`1<float64>, string)
	IL_0058: callvirt instance void [HeavenLens.Data]HeavenLens.Scripts.IScriptContext::InitializeConstant<class [HeavenLens]HeavenLens.RuntimeExpression>(string, !!0)
	IL_005d: ldnull
	IL_005e: ret
} // end of method Statements::l40c5_decl

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions