diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index be0a963cdb794c..81ca09eeccac95 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -1104,10 +1104,6 @@ GenTree* Compiler::fgOptimizeDelegateConstructor(GenTreeCall* call, targetMethodHnd = ldftnToken->m_token.hMethod; } - else - { - assert(targetMethodHnd == nullptr); - } #ifdef FEATURE_READYTORUN if (IsAot()) @@ -1161,7 +1157,7 @@ GenTree* Compiler::fgOptimizeDelegateConstructor(GenTreeCall* call, #ifndef TARGET_WASM // TODO-WASM: Wasm doesn't use the dynamically composed helpers yet. When we do, we probably will // need to use a different set of arguments to construct the right helper call to avoid dynamically // composing a helper - else if (oper == GT_FTN_ADDR) + else if ((oper == GT_FTN_ADDR) && (ldftnToken != nullptr)) { JITDUMP("optimized\n"); diff --git a/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.cs b/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.cs index fcdb479c1a6353..53817d683d204a 100644 --- a/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.cs +++ b/src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.cs @@ -135,6 +135,32 @@ public static void Verify_CallCtorWithEmptyNotNullName() extern static UserDataClass CallPrivateConstructorWithEmptyName(); } + interface IDelegateTarget + { + static virtual object GetValue() => "DelegateTargetValue"; + } + + class DelegateTargetImpl : IDelegateTarget { } + + delegate object DelegateFromUnsafeAccessor(); + + [UnsafeAccessor(UnsafeAccessorKind.Constructor)] + extern static DelegateFromUnsafeAccessor ConstructDelegate(object o, IntPtr p); + + static class DelegateTargetResolver where T : IDelegateTarget + { + public static unsafe delegate* Resolve() => &T.GetValue; + } + + [Fact] + public static unsafe void Verify_ConstructDelegateFromFunctionPointer() + { + Console.WriteLine($"Running {nameof(Verify_ConstructDelegateFromFunctionPointer)}"); + + var del = ConstructDelegate(null, (nint)DelegateTargetResolver.Resolve()); + Assert.Equal("DelegateTargetValue", del()); + } + [Fact] public static void Verify_CallCtorAsMethod() {