diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
index 6b0c50a206d..51174f89320 100644
--- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
+++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
@@ -133,6 +133,7 @@
### Improved
* Nullness warning FS3261 on dotted method or property access (e.g. `x.Member`) now underlines the receiver expression and includes the member name and (when known) the binding name in the message. ([Issue #19658](https://github.com/dotnet/fsharp/issues/19658), [PR #19814](https://github.com/dotnet/fsharp/pull/19814))
+* Direct delegate construction ([PR ##19993](https://github.com/dotnet/fsharp/pull/19993))
### Changed
diff --git a/docs/release-notes/.Language/preview.md b/docs/release-notes/.Language/preview.md
index 8172d510f76..85ffa6886c4 100644
--- a/docs/release-notes/.Language/preview.md
+++ b/docs/release-notes/.Language/preview.md
@@ -8,4 +8,6 @@
### Fixed
-### Changed
\ No newline at end of file
+### Changed
+
+* Direct delegate construction ([PR ##19993](https://github.com/dotnet/fsharp/pull/19993))
\ No newline at end of file
diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs
index 2fda64ce02a..b6f488153b8 100644
--- a/src/Compiler/CodeGen/IlxGen.fs
+++ b/src/Compiler/CodeGen/IlxGen.fs
@@ -25,6 +25,7 @@ open FSharp.Compiler.AbstractIL.ILX
open FSharp.Compiler.AbstractIL.ILX.Types
open FSharp.Compiler.AttributeChecking
open FSharp.Compiler.CompilerGlobalState
+open FSharp.Compiler.DelegateForwarding
open FSharp.Compiler.DiagnosticsLogger
open FSharp.Compiler.Features
open FSharp.Compiler.Infos
@@ -7558,136 +7559,303 @@ and GenDelegateExpr cenv cgbuf eenvouter expr (TObjExprMethod(slotsig, _attribs,
with _ ->
false
- // Work out the free type variables for the morphing thunk
- let takenNames = List.map nameOfVal tmvs
+ let invokeParamInfos =
+ List.replicate (List.concat slotsig.FormalParams).Length ValReprInfo.unnamedTopArg1
- let cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilDelegeeTypeRef, ilCloAllFreeVars, eenvinner =
- GetIlxClosureFreeVars cenv m [] ILBoxity.AsObject eenvouter takenNames expr
+ let numDelegeeParams = invokeParamInfos.Length
- let ilDelegeeGenericParams = GenGenericParams cenv eenvinner cloFreeTyvars
- let ilDelegeeGenericActualsInner = mkILFormalGenericArgs 0 ilDelegeeGenericParams
+ let etaUnitDelegate =
+ match tmvs, invokeParamInfos with
+ | [ _ ], [] -> true
+ | _ -> false
- // When creating a delegate that does not capture any variables, we can instead create a static closure and directly reference the method.
- let useStaticClosure = cloFreeVars.IsEmpty
+ let tmvs, body = BindUnitVars g (tmvs, invokeParamInfos, body)
- // Create a new closure class with a single "delegee" method that implements the delegate.
- let delegeeMethName = "Invoke"
- let ilDelegeeTyInner = mkILBoxedTy ilDelegeeTypeRef ilDelegeeGenericActualsInner
+ // Point the delegate directly at a recognized transparent-forwarding target instead of generating an
+ // intermediate closure; anything unmatched falls back to the closure path below.
+ let directDelegateTarget =
+ if not (g.langVersion.SupportsFeature LanguageFeature.DirectDelegateConstruction) then
+ None
+ elif
+ not cenv.options.localOptimizationsEnabled
+ && (etaUnitDelegate || tmvs |> List.exists (fun v -> not v.IsCompilerGenerated))
+ then
+ // Keep eta-expanded delegates as closures in unoptimized builds so the user's lambda parameter
+ // names survive for debugging; non-eta parameters are synthesized, so nothing is lost there.
+ None
+ else
+ match classifyForwardingTarget (Optimizer.ExprHasEffect Optimizer.EffectContext.Emit) g tmvs body with
+ | DirectDelegateForwardingTargetCandidate.FSharpVal(vref, valUseFlags, tyargs, leadingArgs) ->
+ match StorageForValRef m vref eenvouter with
+ | Method(valReprInfo, vrefM, mspec, _, _, ctps, _, _, _, _, _, _) ->
+ let _, witnessInfos, _, _, _ =
+ GetValReprTypeInCompiledForm g valReprInfo ctps.Length vrefM.Type m
- let envForDelegeeUnderTypars = AddTyparsToEnv methTyparsOfOverridingMethod eenvinner
+ let hasWitnesses = ComputeGenerateWitnesses g eenvouter && not witnessInfos.IsEmpty
- let numthis = if useStaticClosure then 0 else 1
+ match
+ fsharpValDirectlyBindable
+ (Optimizer.ExprHasEffect Optimizer.EffectContext.Emit)
+ g
+ tmvs
+ leadingArgs
+ vrefM
+ valUseFlags
+ hasWitnesses
+ with
+ | ValueSome(virtualCall, takesInstanceArg) ->
+ let ilTyArgs = GenTypeArgs cenv m eenvouter.tyenv tyargs
- let tmvs, body =
- BindUnitVars g (tmvs, List.replicate (List.concat slotsig.FormalParams).Length ValReprInfo.unnamedTopArg1, body)
+ let numEnclILTypeArgs =
+ if vrefM.MemberInfo.IsSome && not vrefM.IsExtensionMember then
+ List.length (vrefM.MemberApparentEntity.Typars |> DropErasedTypars)
+ else
+ 0
- // The slot sig contains a formal instantiation. When creating delegates we're only
- // interested in the actual instantiation since we don't have to emit a method impl.
- let ilDelegeeParams, ilDelegeeRet =
- GenActualSlotsig m cenv envForDelegeeUnderTypars slotsig methTyparsOfOverridingMethod tmvs
+ if ilTyArgs.Length < numEnclILTypeArgs then
+ None
+ else
+ let ilEnclArgTys, ilMethArgTys = List.splitAt numEnclILTypeArgs ilTyArgs
- let envForDelegeeMeth =
- AddStorageForLocalVals g (List.mapi (fun i v -> (v, Arg(i + numthis))) tmvs) envForDelegeeUnderTypars
+ let targetMspec =
+ mkILMethSpec (mspec.MethodRef, mspec.DeclaringType.Boxity, ilEnclArgTys, ilMethArgTys)
- let ilMethodBody =
- CodeGenMethodForExpr
- cenv
- cgbuf.mgbuf
- ([],
- delegeeMethName,
- envForDelegeeMeth,
- 1,
- None,
- body,
- (if slotSigHasVoidReturnTy slotsig then
- discardAndReturnVoid
- else
- Return))
+ let numBoundLeadingFormals = if takesInstanceArg then 0 else leadingArgs.Length
- let delegeeInvokeMeth =
- (if useStaticClosure then
- mkILNonGenericStaticMethod
- else
- mkILNonGenericInstanceMethod) (
- delegeeMethName,
- ILMemberAccess.Assembly,
- ilDelegeeParams,
- ilDelegeeRet,
- MethodBody.IL(InterruptibleLazy.FromValue ilMethodBody)
- )
+ if takesInstanceArg <> targetMspec.MethodRef.CallingConv.IsInstance then
+ None
+ else
+ let ilDelegeeRetTy =
+ let envUnderTypars = AddTyparsToEnv methTyparsOfOverridingMethod eenvouter
- let delegeeCtorMeth =
- mkILSimpleStorageCtor (Some g.ilg.typ_Object.TypeSpec, ilDelegeeTyInner, [], [], ILMemberAccess.Assembly, None, eenvouter.imports)
+ let _, ilDelegeeRet =
+ GenActualSlotsig m cenv envUnderTypars slotsig methTyparsOfOverridingMethod tmvs
- let ilCtorBody = delegeeCtorMeth.MethodBody
+ ilDelegeeRet.Type
- let ilCloLambdas = Lambdas_return ilCtxtDelTy
+ if
+ signatureMatches
+ numBoundLeadingFormals
+ numDelegeeParams
+ ilDelegeeRetTy
+ ilEnclArgTys
+ ilMethArgTys
+ targetMspec
+ then
+ Some(targetMspec, receiverInfo leadingArgs virtualCall)
+ else
+ None
+ | ValueNone -> None
+ | _ -> None
- let cloTypeDefs =
- (if useStaticClosure then
- GenStaticDelegateClosureTypeDefs
- else
- GenClosureTypeDefs)
- cenv
- (ilDelegeeTypeRef,
- ilDelegeeGenericParams,
- [],
- ilCloAllFreeVars,
- ilCloLambdas,
- ilCtorBody,
- [ delegeeInvokeMeth ],
- [],
- g.ilg.typ_Object,
- [],
- None)
+ | DirectDelegateForwardingTargetCandidate.ILMethod(isVirtual,
+ isStruct,
+ isCtor,
+ valUseFlag,
+ ilMethRef,
+ enclTypeInst,
+ methInst,
+ leadingArgs) ->
+ if
+ ilMethodDirectlyBindable
+ (Optimizer.ExprHasEffect Optimizer.EffectContext.Emit)
+ g
+ tmvs
+ leadingArgs
+ ilMethRef
+ valUseFlag
+ isCtor
+ then
+ let ilEnclArgTys = GenTypeArgs cenv m eenvouter.tyenv enclTypeInst
+ let ilMethArgTys = GenTypeArgs cenv m eenvouter.tyenv methInst
+ let boxity = if isStruct then AsValue else AsObject
+ let targetMspec = mkILMethSpec (ilMethRef, boxity, ilEnclArgTys, ilMethArgTys)
+
+ let numBoundLeadingFormals =
+ if ilMethRef.CallingConv.IsInstance then
+ 0
+ else
+ leadingArgs.Length
- for cloTypeDef in cloTypeDefs do
- cgbuf.mgbuf.AddTypeDef(ilDelegeeTypeRef, cloTypeDef, false, false, None, m)
+ // Imported metadata carries different assembly scope refs than the compiler-generated
+ // delegee types, so structural IL type comparison reports false negatives even for
+ // primitives; the arity check is the sound residual guard (the call is already typed).
+ if targetMspec.FormalArgTypes.Length - numBoundLeadingFormals = numDelegeeParams then
+ Some(targetMspec, receiverInfo leadingArgs isVirtual)
+ else
+ None
+ else
+ None
- CountClosure()
+ | DirectDelegateForwardingTargetCandidate.Other -> None
- // Push the constructor for the delegee
- let ctxtGenericArgsForDelegee = GenGenericArgs m eenvouter.tyenv cloFreeTyvars
+ match directDelegateTarget with
+ | Some(targetMspec, receiverInfo) ->
+ match receiverInfo with
+ | None ->
+ // Static target: null Target.
+ GenUnit cenv eenvouter m cgbuf
+ CG.EmitInstr cgbuf (pop 0) (Push [ g.ilg.typ_IntPtr ]) (I_ldftn targetMspec)
+ | Some(receiverExpr, isVirtual) ->
+ // Instance target: the receiver becomes the Target.
+ GenExpr cenv cgbuf eenvouter receiverExpr Continue
+
+ if targetMspec.DeclaringType.Boxity.IsAsValue then
+ // Box a copy as the 'object' Target; invocation reaches 'this' through the runtime's
+ // unboxing stub, matching the closure's by-value capture. (Struct instance methods are
+ // non-virtual, so the ldftn path below is taken.)
+ CG.EmitInstr cgbuf (pop 1) (Push [ g.ilg.typ_Object ]) (I_box targetMspec.DeclaringType)
+
+ if isVirtual then
+ // dup the receiver so ldvirtftn can bind its runtime type's override.
+ CG.EmitInstr cgbuf (pop 0) (Push [ targetMspec.DeclaringType ]) AI_dup
+ CG.EmitInstr cgbuf (pop 1) (Push [ g.ilg.typ_IntPtr ]) (I_ldvirtftn targetMspec)
+ else
+ CG.EmitInstr cgbuf (pop 0) (Push [ g.ilg.typ_IntPtr ]) (I_ldftn targetMspec)
- if useStaticClosure then
- GenUnit cenv eenvouter m cgbuf
- else
- let ilxCloSpec =
- IlxClosureSpec.Create(IlxClosureRef(ilDelegeeTypeRef, ilCloLambdas, ilCloAllFreeVars), ctxtGenericArgsForDelegee, false)
+ // newobj Delegate::.ctor(object, native int)
+ let ilDelegeeCtorMethOuter =
+ mkCtorMethSpecForDelegate g.ilg (ilCtxtDelTy, useUIntPtrForDelegateCtor)
- GenWitnessArgsFromWitnessInfos cenv cgbuf eenvouter m cloWitnessInfos
+ CG.EmitInstr cgbuf (pop 2) (Push [ ilCtxtDelTy ]) (I_newobj(ilDelegeeCtorMethOuter, None))
+ GenSequel cenv eenvouter.cloc cgbuf sequel
- for fv in cloFreeVars do
- GenGetFreeVarForClosure cenv cgbuf eenvouter m fv
+ | None ->
+ let takenNames = List.map nameOfVal tmvs
- CG.EmitInstr
- cgbuf
- (pop ilCloAllFreeVars.Length)
- (Push [ EraseClosures.mkTyOfLambdas cenv.ilxPubCloEnv ilCloLambdas ])
- (I_newobj(ilxCloSpec.Constructor, None))
+ // Work out the free type variables for the morphing thunk
+ let cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilDelegeeTypeRef, ilCloAllFreeVars, eenvinner =
+ GetIlxClosureFreeVars cenv m [] ILBoxity.AsObject eenvouter takenNames expr
- // Push the function pointer to the Invoke method of the delegee
- let ilDelegeeTyOuter = mkILBoxedTy ilDelegeeTypeRef ctxtGenericArgsForDelegee
+ let ilDelegeeGenericParams = GenGenericParams cenv eenvinner cloFreeTyvars
+ let ilDelegeeGenericActualsInner = mkILFormalGenericArgs 0 ilDelegeeGenericParams
- let ilDelegeeInvokeMethOuter =
- (if useStaticClosure then
- mkILNonGenericStaticMethSpecInTy
- else
- mkILNonGenericInstanceMethSpecInTy) (
- ilDelegeeTyOuter,
- "Invoke",
- typesOfILParams ilDelegeeParams,
- ilDelegeeRet.Type
- )
+ // When creating a delegate that does not capture any variables, we can instead create a static closure and directly reference the method.
+ let useStaticClosure = cloFreeVars.IsEmpty
- CG.EmitInstr cgbuf (pop 0) (Push [ g.ilg.typ_IntPtr ]) (I_ldftn ilDelegeeInvokeMethOuter)
+ // Create a new closure class with a single "delegee" method that implements the delegate.
+ let delegeeMethName = "Invoke"
+ let ilDelegeeTyInner = mkILBoxedTy ilDelegeeTypeRef ilDelegeeGenericActualsInner
- // Instantiate the delegate
- let ilDelegeeCtorMethOuter =
- mkCtorMethSpecForDelegate g.ilg (ilCtxtDelTy, useUIntPtrForDelegateCtor)
+ let envForDelegeeUnderTypars = AddTyparsToEnv methTyparsOfOverridingMethod eenvinner
- CG.EmitInstr cgbuf (pop 2) (Push [ ilCtxtDelTy ]) (I_newobj(ilDelegeeCtorMethOuter, None))
- GenSequel cenv eenvouter.cloc cgbuf sequel
+ let numthis = if useStaticClosure then 0 else 1
+
+ // The slot sig contains a formal instantiation. When creating delegates we're only
+ // interested in the actual instantiation since we don't have to emit a method impl.
+ let ilDelegeeParams, ilDelegeeRet =
+ GenActualSlotsig m cenv envForDelegeeUnderTypars slotsig methTyparsOfOverridingMethod tmvs
+
+ let envForDelegeeMeth =
+ AddStorageForLocalVals g (List.mapi (fun i v -> (v, Arg(i + numthis))) tmvs) envForDelegeeUnderTypars
+
+ let ilMethodBody =
+ CodeGenMethodForExpr
+ cenv
+ cgbuf.mgbuf
+ ([],
+ delegeeMethName,
+ envForDelegeeMeth,
+ 1,
+ None,
+ body,
+ (if slotSigHasVoidReturnTy slotsig then
+ discardAndReturnVoid
+ else
+ Return))
+
+ let delegeeInvokeMeth =
+ (if useStaticClosure then
+ mkILNonGenericStaticMethod
+ else
+ mkILNonGenericInstanceMethod) (
+ delegeeMethName,
+ ILMemberAccess.Assembly,
+ ilDelegeeParams,
+ ilDelegeeRet,
+ MethodBody.IL(InterruptibleLazy.FromValue ilMethodBody)
+ )
+
+ let delegeeCtorMeth =
+ mkILSimpleStorageCtor (
+ Some g.ilg.typ_Object.TypeSpec,
+ ilDelegeeTyInner,
+ [],
+ [],
+ ILMemberAccess.Assembly,
+ None,
+ eenvouter.imports
+ )
+
+ let ilCtorBody = delegeeCtorMeth.MethodBody
+
+ let ilCloLambdas = Lambdas_return ilCtxtDelTy
+
+ let cloTypeDefs =
+ (if useStaticClosure then
+ GenStaticDelegateClosureTypeDefs
+ else
+ GenClosureTypeDefs)
+ cenv
+ (ilDelegeeTypeRef,
+ ilDelegeeGenericParams,
+ [],
+ ilCloAllFreeVars,
+ ilCloLambdas,
+ ilCtorBody,
+ [ delegeeInvokeMeth ],
+ [],
+ g.ilg.typ_Object,
+ [],
+ None)
+
+ for cloTypeDef in cloTypeDefs do
+ cgbuf.mgbuf.AddTypeDef(ilDelegeeTypeRef, cloTypeDef, false, false, None, m)
+
+ CountClosure()
+
+ // Push the constructor for the delegee
+ let ctxtGenericArgsForDelegee = GenGenericArgs m eenvouter.tyenv cloFreeTyvars
+
+ if useStaticClosure then
+ GenUnit cenv eenvouter m cgbuf
+ else
+ let ilxCloSpec =
+ IlxClosureSpec.Create(IlxClosureRef(ilDelegeeTypeRef, ilCloLambdas, ilCloAllFreeVars), ctxtGenericArgsForDelegee, false)
+
+ GenWitnessArgsFromWitnessInfos cenv cgbuf eenvouter m cloWitnessInfos
+
+ for fv in cloFreeVars do
+ GenGetFreeVarForClosure cenv cgbuf eenvouter m fv
+
+ CG.EmitInstr
+ cgbuf
+ (pop ilCloAllFreeVars.Length)
+ (Push [ EraseClosures.mkTyOfLambdas cenv.ilxPubCloEnv ilCloLambdas ])
+ (I_newobj(ilxCloSpec.Constructor, None))
+
+ // Push the function pointer to the Invoke method of the delegee
+ let ilDelegeeTyOuter = mkILBoxedTy ilDelegeeTypeRef ctxtGenericArgsForDelegee
+
+ let ilDelegeeInvokeMethOuter =
+ (if useStaticClosure then
+ mkILNonGenericStaticMethSpecInTy
+ else
+ mkILNonGenericInstanceMethSpecInTy) (
+ ilDelegeeTyOuter,
+ "Invoke",
+ typesOfILParams ilDelegeeParams,
+ ilDelegeeRet.Type
+ )
+
+ CG.EmitInstr cgbuf (pop 0) (Push [ g.ilg.typ_IntPtr ]) (I_ldftn ilDelegeeInvokeMethOuter)
+
+ // Instantiate the delegate
+ let ilDelegeeCtorMethOuter =
+ mkCtorMethSpecForDelegate g.ilg (ilCtxtDelTy, useUIntPtrForDelegateCtor)
+
+ CG.EmitInstr cgbuf (pop 2) (Push [ ilCtxtDelTy ]) (I_newobj(ilDelegeeCtorMethOuter, None))
+ GenSequel cenv eenvouter.cloc cgbuf sequel
/// Used to search FSharp.Core implementations of "^T : ^T" and decide whether the conditional activates
and ExprIsTraitCall expr =
diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt
index c6cbc797da5..173e2bed8a8 100644
--- a/src/Compiler/FSComp.txt
+++ b/src/Compiler/FSComp.txt
@@ -1824,5 +1824,6 @@ featurePreprocessorElif,"#elif preprocessor directive"
3890,tcRecursiveInlineNotAllowed,"The value or member '%s' has been marked 'inline' but is part of a recursive binding group. F# does not support recursive 'inline' values. Either remove the 'inline' modifier or refactor the recursion."
featureExceptionFieldSerializationSupport,"emit GetObjectData and field-restoring deserialization constructor for exception types"
featureErrorOnMissingSignatureAttribute,"error (rather than warning) when an enforced compiler-semantic attribute is present in the .fs but missing from the .fsi"
+featureDirectDelegateConstruction,"construct delegates that point directly at the target method, avoiding an intermediate closure"
featureAccessProtectedBaseFieldFromClosure,"Access a protected base-class field from a closure inside a member"
featureImprovedImpliedArgumentNamesPartTwo,"Improved implied argument names with partial application"
diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj
index 5510af6b3f6..c29afb5c369 100644
--- a/src/Compiler/FSharp.Compiler.Service.fsproj
+++ b/src/Compiler/FSharp.Compiler.Service.fsproj
@@ -418,6 +418,7 @@
+
diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs
index 9ecc56472c6..199b759e0ff 100644
--- a/src/Compiler/Facilities/LanguageFeatures.fs
+++ b/src/Compiler/Facilities/LanguageFeatures.fs
@@ -110,6 +110,7 @@ type LanguageFeature =
| PreprocessorElif
| ExceptionFieldSerializationSupport
| ErrorOnMissingSignatureAttribute
+ | DirectDelegateConstruction
| AccessProtectedBaseFieldFromClosure
| ImprovedImpliedArgumentNamesPartTwo
@@ -266,6 +267,7 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array)
LanguageFeature.MethodOverloadsCache, previewVersion // Performance optimization for overload resolution
LanguageFeature.ImplicitDIMCoverage, languageVersion110
LanguageFeature.ErrorOnMissingSignatureAttribute, previewVersion // Opt-in: turn FS3888 from warning into error
+ LanguageFeature.DirectDelegateConstruction, previewVersion
LanguageFeature.AccessProtectedBaseFieldFromClosure, previewVersion // #5302: read a protected base field from a closure
]
@@ -463,6 +465,7 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array)
| LanguageFeature.PreprocessorElif -> FSComp.SR.featurePreprocessorElif ()
| LanguageFeature.ExceptionFieldSerializationSupport -> FSComp.SR.featureExceptionFieldSerializationSupport ()
| LanguageFeature.ErrorOnMissingSignatureAttribute -> FSComp.SR.featureErrorOnMissingSignatureAttribute ()
+ | LanguageFeature.DirectDelegateConstruction -> FSComp.SR.featureDirectDelegateConstruction ()
| LanguageFeature.AccessProtectedBaseFieldFromClosure -> FSComp.SR.featureAccessProtectedBaseFieldFromClosure ()
| LanguageFeature.ImprovedImpliedArgumentNamesPartTwo -> FSComp.SR.featureImprovedImpliedArgumentNamesPartTwo ()
diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi
index 4aa85a42224..76ce2d75236 100644
--- a/src/Compiler/Facilities/LanguageFeatures.fsi
+++ b/src/Compiler/Facilities/LanguageFeatures.fsi
@@ -101,6 +101,7 @@ type LanguageFeature =
| PreprocessorElif
| ExceptionFieldSerializationSupport
| ErrorOnMissingSignatureAttribute
+ | DirectDelegateConstruction
| AccessProtectedBaseFieldFromClosure
| ImprovedImpliedArgumentNamesPartTwo
diff --git a/src/Compiler/Optimize/DelegateForwarding.fs b/src/Compiler/Optimize/DelegateForwarding.fs
new file mode 100644
index 00000000000..c720f9bf1b5
--- /dev/null
+++ b/src/Compiler/Optimize/DelegateForwarding.fs
@@ -0,0 +1,282 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+/// Recognition of delegate constructions whose Invoke body is a transparent forwarding call to a known
+/// method, shared by the optimizer (which preserves the call from inlining) and the ILX generator (which
+/// points the delegate directly at the target). The 'exprHasEffect' parameter is Optimizer.ExprHasEffect;
+/// it is passed in because this file compiles before the optimizer.
+module internal FSharp.Compiler.DelegateForwarding
+
+open Internal.Utilities.Collections
+
+open FSharp.Compiler.AbstractIL.IL
+open FSharp.Compiler.TcGlobals
+open FSharp.Compiler.TypedTree
+open FSharp.Compiler.TypedTreeBasics
+open FSharp.Compiler.TypedTreeOps
+
+/// A delegate target that can potentially be forwarded to directly, without an intermediate closure
+[]
+type DirectDelegateForwardingTargetCandidate =
+ /// A known F# value: a module-level function or a member
+ | FSharpVal of vref: ValRef * valUseFlags: ValUseFlag * tyargs: TypeInst * leadingArgs: Expr list
+ /// A direct IL method call (e.g. a BCL method)
+ | ILMethod of
+ isVirtual: bool *
+ isStruct: bool *
+ isCtor: bool *
+ valUseFlags: ValUseFlag *
+ ilMethRef: ILMethodRef *
+ enclTypeInst: TypeInst *
+ methInst: TypeInst *
+ leadingArgs: Expr list
+ | Other
+
+let private isUnitValue e =
+ match stripDebugPoints e with
+ | Expr.Const(Const.Unit, _, _) -> true
+ | _ -> false
+
+// Mirror the code generator's arity-based de-tupling (a tupled argument group is one tuple node in the
+// call but separate IL parameters in the compiled target) so the match sees the flattened argument list.
+// The group count must equal the target's arity exactly: fewer is a partial application, more an
+// over-application whose trailing arguments are consumed by the target's *result*, and a target without
+// arity information has no compiled method to point at.
+let private tryFlattenTupledArgs (vref: ValRef) (args: Expr list) =
+ let arities = (arityOfVal vref.Deref).AritiesOfArgs
+
+ if arities.Length <> args.Length then
+ None
+ else
+ (arities, args)
+ ||> List.map2 (fun arity arg ->
+ match stripDebugPoints arg with
+ | Expr.Op(TOp.Tuple _, _, elems, _) when arity >= 2 && elems.Length = arity -> elems
+ | _ -> [ arg ])
+ |> List.concat
+ |> Some
+
+let rec private resolveAliases (aliases: ValMap) e =
+ let e = stripDebugPoints e
+
+ match e with
+ | Expr.Val(vref, _, _) ->
+ match aliases.TryFind vref.Deref with
+ | Some e2 -> resolveAliases aliases e2
+ | None -> e
+ | _ -> e
+
+// Trailing arguments must be the delegate's Invoke parameters, verbatim and in order; the leading rest
+// (e.g. an instance receiver) is resolved and returned for the caller to check and emit.
+let private matchForwarding g (aliases: ValMap) (invokeParams: Val list) (args: Expr list) =
+ let args = args |> List.map (resolveAliases aliases)
+
+ // Drop the elided unit argument when the Invoke takes no parameters.
+ let args =
+ match List.tryLast args with
+ | Some last when List.isEmpty invokeParams && isUnitValue last -> List.truncate (args.Length - 1) args
+ | _ -> args
+
+ let numLeading = args.Length - invokeParams.Length
+
+ if numLeading >= 0 then
+ let leadingArgs, forwardedArgs = List.splitAt numLeading args
+
+ if
+ List.forall2
+ (fun (a: Expr) (tv: Val) ->
+ match a with
+ | Expr.Val(avref, _, _) -> valRefEq g avref (mkLocalValRef tv)
+ | _ -> false)
+ forwardedArgs
+ invokeParams
+ then
+ // A struct receiver arrives by address; recover the value so the emit can box it as the
+ // Target (invocation reaches 'this' through the runtime's unboxing stub).
+ let leadingArgs =
+ leadingArgs
+ |> List.map (fun a ->
+ match a with
+ | Expr.Op(TOp.LValueOp(LAddrOf _, vref), _, _, m) -> resolveAliases aliases (exprForValRef m vref)
+ | _ -> a)
+
+ Some leadingArgs
+ else
+ None
+ else
+ None
+
+// Peel the wrappers the elaborator and BuildNewDelegateExpr leave around the forwarding call: effect-free
+// let-bindings, applications of let-wrapped or immediate lambdas (method-group coercions, the shells of
+// curried member calls), and curried application nesting. The optimizer reduces these only while already
+// making inlining decisions - too late for a recognizer that must precede them - so peel by aliasing:
+// each bound value maps to the expression flowing into it, resolved when the arguments are matched.
+// Anything else is left in place and fails the match, conservatively keeping the closure.
+let rec private stripToForwardingCall exprHasEffect g (aliases: ValMap) expr =
+ match stripDebugPoints expr with
+ | Expr.Let(TBind(v, rhs, _), inner, _, _) when not (exprHasEffect g rhs) ->
+ stripToForwardingCall exprHasEffect g (aliases.Add v rhs) inner
+ | Expr.App(f, fty, tyargs, args, m) as app ->
+ match stripDebugPoints f with
+ | Expr.Let(TBind(v, rhs, _), f2, _, _) when not (exprHasEffect g rhs) ->
+ stripToForwardingCall exprHasEffect g (aliases.Add v rhs) (Expr.App(f2, fty, tyargs, args, m))
+ | Expr.Lambda(_, None, None, [ v ], body, _, _) when List.isEmpty tyargs ->
+ match args with
+ | a :: rest when not (exprHasEffect g a) ->
+ let aliases = aliases.Add v a
+
+ match rest with
+ | [] -> stripToForwardingCall exprHasEffect g aliases body
+ | _ -> stripToForwardingCall exprHasEffect g aliases (Expr.App(body, tyOfExpr g body, [], rest, m))
+ | _ -> app, aliases
+ | Expr.App(f2, f2ty, tyargs2, args2, _) when List.isEmpty tyargs ->
+ stripToForwardingCall exprHasEffect g aliases (Expr.App(f2, f2ty, tyargs2, args2 @ args, m))
+ | _ -> app, aliases
+ | e -> e, aliases
+
+let classifyForwardingTarget exprHasEffect g (invokeParams: Val list) expr =
+ let call, aliases = stripToForwardingCall exprHasEffect g ValMap.Empty expr
+
+ match call with
+ | Expr.App(f, _, tyargs, args, _) ->
+ match stripDebugPoints f with
+ | Expr.Val(vref, valUseFlags, _) ->
+ match
+ tryFlattenTupledArgs vref args
+ |> Option.bind (matchForwarding g aliases invokeParams)
+ with
+ | Some leadingArgs -> DirectDelegateForwardingTargetCandidate.FSharpVal(vref, valUseFlags, tyargs, leadingArgs)
+ | None -> DirectDelegateForwardingTargetCandidate.Other
+ | _ -> DirectDelegateForwardingTargetCandidate.Other
+ | Expr.Op(TOp.ILCall(isVirtual, _, isStruct, isCtor, valUseFlag, _, _, ilMethRef, enclTypeInst, methInst, _), _, args, _) ->
+ match matchForwarding g aliases invokeParams args with
+ | Some leadingArgs ->
+ DirectDelegateForwardingTargetCandidate.ILMethod(
+ isVirtual,
+ isStruct,
+ isCtor,
+ valUseFlag,
+ ilMethRef,
+ enclTypeInst,
+ methInst,
+ leadingArgs
+ )
+ | None -> DirectDelegateForwardingTargetCandidate.Other
+ | _ -> DirectDelegateForwardingTargetCandidate.Other
+
+/// At most one leading argument can become the delegate's Target: the receiver of an instance target, or
+/// the first parameter of a static one via the CLR's "closed over the first argument" delegate form
+/// (extension-member receivers, one-argument partial applications). More has no closed form.
+let private receiverShapeOk (leadingArgs: Expr list) takesInstanceArg =
+ if takesInstanceArg then
+ match leadingArgs with
+ | [ _ ] -> true
+ | _ -> false
+ else
+ match leadingArgs with
+ | []
+ | [ _ ] -> true
+ | _ -> false
+
+/// The closed-delegate thunk passes the Target into a static target's first parameter with no unboxing,
+/// so a value-type leading argument has no closed form (unlike an instance receiver's unboxing stub).
+let private staticLeadingArgIsRefType g takesInstanceArg (leadingArgs: Expr list) =
+ match leadingArgs with
+ | [ recv ] when not takesInstanceArg -> not (isStructTy g (tyOfExpr g recv))
+ | _ -> true
+
+/// Boxing the receiver needs it as a value: '&localVar' is recovered by the recognizer, but any other
+/// address form leaves a byref the box cannot consume.
+let private receiverNotByref g (leadingArgs: Expr list) =
+ match leadingArgs with
+ | [ recv ] -> not (isByrefTy g (tyOfExpr g recv))
+ | _ -> true
+
+/// The receiver is evaluated once at the construction site rather than on every Invoke, which is only
+/// unobservable when it is effect-free; and it must not reference the Invoke parameters, which exist
+/// only inside the delegee.
+let private receiverBindable exprHasEffect g (invokeParams: Val list) (leadingArgs: Expr list) =
+ match leadingArgs with
+ | [ recv ] ->
+ let recvFreeLocals = (freeInExpr CollectLocals recv).FreeLocals
+
+ not (exprHasEffect g recv)
+ && (not (invokeParams |> List.exists (fun tv -> Zset.contains tv recvFreeLocals)))
+ | _ -> true
+
+/// Returns the virtual-call and instance-receiver facts derived from the member call info when the
+/// target is directly bindable. Witnesses are passed in: computing them needs the IlxGen environment.
+let fsharpValDirectlyBindable
+ exprHasEffect
+ g
+ (invokeParams: Val list)
+ (leadingArgs: Expr list)
+ (vrefM: ValRef)
+ (valUseFlags: ValUseFlag)
+ hasWitnesses
+ =
+ let _, virtualCall, newobj, isSuperInit, isSelfInit, takesInstanceArg, _, _ =
+ GetMemberCallInfo g (vrefM, valUseFlags)
+
+ if
+ not hasWitnesses
+ && not newobj
+ && not isSuperInit
+ && not isSelfInit
+ && not valUseFlags.IsVSlotDirectCall
+ && receiverShapeOk leadingArgs takesInstanceArg
+ && receiverBindable exprHasEffect g invokeParams leadingArgs
+ && staticLeadingArgIsRefType g takesInstanceArg leadingArgs
+ && receiverNotByref g leadingArgs
+ then
+ ValueSome(virtualCall, takesInstanceArg)
+ else
+ ValueNone
+
+let ilMethodDirectlyBindable
+ exprHasEffect
+ g
+ (invokeParams: Val list)
+ (leadingArgs: Expr list)
+ (ilMethRef: ILMethodRef)
+ (valUseFlag: ValUseFlag)
+ isCtor
+ =
+ let takesInstanceArg = ilMethRef.CallingConv.IsInstance
+
+ not isCtor
+ && not valUseFlag.IsVSlotDirectCall
+ && not valUseFlag.IsPossibleConstrainedCall
+ && receiverShapeOk leadingArgs takesInstanceArg
+ && receiverBindable exprHasEffect g invokeParams leadingArgs
+ && staticLeadingArgIsRefType g takesInstanceArg leadingArgs
+ && receiverNotByref g leadingArgs
+
+/// Residual IL compatibility check; the type checker verified the call and the forwarding match pinned
+/// the shape. Parameter types are deliberately not compared - value types are exact by construction and
+/// reference types may use the CLR's contravariant delegate relaxation - only their count, minus any
+/// leading formals consumed by a bound Target. The return type must match exactly for a non-generic
+/// target (the CLR does not relax e.g. 'void' against 'Unit'); a generic target's return is written in
+/// type variables, where no exact comparison is meaningful.
+let signatureMatches
+ numBoundLeadingFormals
+ (numDelegeeParams: int)
+ (ilDelegeeRetTy: ILType)
+ (ilEnclArgTys: ILType list)
+ (ilMethArgTys: ILType list)
+ (targetMspec: ILMethodSpec)
+ =
+ let arityMatches =
+ targetMspec.FormalArgTypes.Length - numBoundLeadingFormals = numDelegeeParams
+
+ let returnMatches =
+ if List.isEmpty ilEnclArgTys && List.isEmpty ilMethArgTys then
+ ilDelegeeRetTy = targetMspec.FormalReturnType
+ else
+ true
+
+ arityMatches && returnMatches
+
+let receiverInfo (leadingArgs: Expr list) virtualCall =
+ match leadingArgs with
+ | [ recv ] -> Some(recv, virtualCall)
+ | _ -> None
diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs
index f67072c1c78..1e8afe2fafd 100644
--- a/src/Compiler/Optimize/Optimizer.fs
+++ b/src/Compiler/Optimize/Optimizer.fs
@@ -12,6 +12,7 @@ open FSharp.Compiler
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.AttributeChecking
open FSharp.Compiler.CompilerGlobalState
+open FSharp.Compiler.DelegateForwarding
open FSharp.Compiler.DiagnosticsLogger
open FSharp.Compiler.Text.Range
open FSharp.Compiler.Syntax.PrettyNaming
@@ -1707,7 +1708,7 @@ and OpHasEffect context g m op tyargs =
| TOp.ExnFieldSet _
| TOp.Coerce
| TOp.Reraise
- | TOp.IntegerForLoop _
+ | TOp.IntegerForLoop _
| TOp.While _
| TOp.TryWith _ (* conservative *)
| TOp.TryFinally _ (* conservative *)
@@ -1722,6 +1723,43 @@ and OpHasEffect context g m op tyargs =
let effectContextOf (cenv: cenv) =
if cenv.optimizing then EffectContext.Emit else EffectContext.InlineBody
+/// Prevent the optimizer from inlining a recognized direct-delegate forwarding target into the delegate
+/// body: inlining would dissolve the call before IlxGen can point the delegate at it, making the emitted
+/// form depend on the target's size (locally, and through a referenced assembly's optimization data).
+/// Mandatory inlining of 'inline' values takes precedence via OptimizeVal.
+let AddDirectDelegateTargetToDontInlineSet cenv env (slotsig: SlotSig) tmvs body m =
+ let g = cenv.g
+
+ if
+ g.langVersion.SupportsFeature Features.LanguageFeature.DirectDelegateConstruction
+ && cenv.optimizing
+ && cenv.settings.InlineLambdas
+ then
+ let exprHasEffect = ExprHasEffect (effectContextOf cenv)
+
+ // Normalize the elided unit parameter of a zero-parameter Invoke (e.g. System.Action) exactly as
+ // IlxGen will before it runs the recognizer
+ let tmvs, body =
+ if slotsig.FormalParams |> List.forall List.isEmpty then
+ BindUnitVars g (tmvs, [], body)
+ else
+ tmvs, body
+
+ match classifyForwardingTarget exprHasEffect g tmvs body with
+ | DirectDelegateForwardingTargetCandidate.FSharpVal(vref, valUseFlags, _, leadingArgs) when
+ // ValReprInfo.IsSome mirrors IlxGen's Method-storage requirement. Witnesses are not knowable
+ // here; over-suppressing a witness-requiring target only costs an inline in a closure body.
+ vref.ValReprInfo.IsSome
+ && (fsharpValDirectlyBindable exprHasEffect g tmvs leadingArgs vref valUseFlags false)
+ .IsSome
+ ->
+ match (GetInfoForVal cenv env m vref).ValExprInfo with
+ | StripLambdaValue(lambdaId, _, _, _, _) ->
+ { env with dontInline = Map.add lambdaId [] env.dontInline }
+ | _ -> env
+ | _ -> env
+ else
+ env
let TryEliminateBinding cenv _env bind e2 _m =
let g = cenv.g
@@ -2441,11 +2479,16 @@ let rec OptimizeExpr cenv (env: IncrementalOptimizationEnv) expr =
MightMakeCriticalTailcall=false
Info=UnknownValue }
- | Expr.Obj (_, ty, basev, createExpr, overrides, iimpls, m) ->
- match expr with
- | NewDelegateExpr g (lambdaId, vsl, body, _, remake) ->
+ | Expr.Obj (_, ty, basev, createExpr, overrides, iimpls, m) ->
+ match expr with
+ | NewDelegateExpr g (lambdaId, vsl, body, _, remake) ->
+ let env =
+ match overrides with
+ | [ TObjExprMethod(slotsig, _, _, _, _, mMeth) ] ->
+ AddDirectDelegateTargetToDontInlineSet cenv env slotsig vsl body mMeth
+ | _ -> env
OptimizeNewDelegateExpr cenv env (lambdaId, vsl, body, remake)
- | _ ->
+ | _ ->
OptimizeObjectExpr cenv env (ty, basev, createExpr, overrides, iimpls, m)
| Expr.Op (op, tyargs, args, m) ->
diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf
index 48fae4742da..478b952edc1 100644
--- a/src/Compiler/xlf/FSComp.txt.cs.xlf
+++ b/src/Compiler/xlf/FSComp.txt.cs.xlf
@@ -367,6 +367,11 @@
Deprecate places where 'seq' can be omitted
+
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+
+
discard pattern in use binding
vzor discard ve vazbě použití
diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf
index 256a5b49e0f..4845e1b9591 100644
--- a/src/Compiler/xlf/FSComp.txt.de.xlf
+++ b/src/Compiler/xlf/FSComp.txt.de.xlf
@@ -367,6 +367,11 @@
Deprecate places where 'seq' can be omitted
+
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+
+
discard pattern in use binding
Das Verwerfen des verwendeten Musters ist verbindlich.
diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf
index 965b77b54c1..52738ac8dd0 100644
--- a/src/Compiler/xlf/FSComp.txt.es.xlf
+++ b/src/Compiler/xlf/FSComp.txt.es.xlf
@@ -367,6 +367,11 @@
Deprecate places where 'seq' can be omitted
+
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+
+
discard pattern in use binding
descartar enlace de patrón en uso
diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf
index 36af4f462ea..4a4bb89f563 100644
--- a/src/Compiler/xlf/FSComp.txt.fr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.fr.xlf
@@ -367,6 +367,11 @@
Deprecate places where 'seq' can be omitted
+
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+
+
discard pattern in use binding
annuler le modèle dans la liaison d’utilisation
diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf
index cf5834247b2..b5b3316708d 100644
--- a/src/Compiler/xlf/FSComp.txt.it.xlf
+++ b/src/Compiler/xlf/FSComp.txt.it.xlf
@@ -367,6 +367,11 @@
Deprecate places where 'seq' can be omitted
+
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+
+
discard pattern in use binding
rimuovi criterio nell'utilizzo dell'associazione
diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf
index d684f435a7f..aef60cd08b5 100644
--- a/src/Compiler/xlf/FSComp.txt.ja.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ja.xlf
@@ -367,6 +367,11 @@
Deprecate places where 'seq' can be omitted
+
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+
+
discard pattern in use binding
使用バインドでパターンを破棄する
diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf
index ae0bdce0e1f..7ea2563baaf 100644
--- a/src/Compiler/xlf/FSComp.txt.ko.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ko.xlf
@@ -367,6 +367,11 @@
Deprecate places where 'seq' can be omitted
+
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+
+
discard pattern in use binding
사용 중인 패턴 바인딩 무시
diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf
index e7f9fbedc3e..3cc10ec0448 100644
--- a/src/Compiler/xlf/FSComp.txt.pl.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pl.xlf
@@ -367,6 +367,11 @@
Deprecate places where 'seq' can be omitted
+
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+
+
discard pattern in use binding
odrzuć wzorzec w powiązaniu użycia
diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
index 2ee0777fb1b..fc43f3f6faf 100644
--- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
@@ -367,6 +367,11 @@
Deprecate places where 'seq' can be omitted
+
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+
+
discard pattern in use binding
descartar o padrão em uso de associação
diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf
index 4b425932b82..cad6afcf849 100644
--- a/src/Compiler/xlf/FSComp.txt.ru.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ru.xlf
@@ -367,6 +367,11 @@
Deprecate places where 'seq' can be omitted
+
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+
+
discard pattern in use binding
шаблон отмены в привязке использования
diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf
index 851fc063da5..b4b623b0f14 100644
--- a/src/Compiler/xlf/FSComp.txt.tr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.tr.xlf
@@ -367,6 +367,11 @@
Deprecate places where 'seq' can be omitted
+
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+
+
discard pattern in use binding
kullanım bağlamasında deseni at
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
index 589fc4eac1a..c068aab598a 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
@@ -367,6 +367,11 @@
Deprecate places where 'seq' can be omitted
+
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+
+
discard pattern in use binding
放弃使用绑定模式
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
index e3f84137cdb..35835c63633 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
@@ -367,6 +367,11 @@
Deprecate places where 'seq' can be omitted
+
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+ construct delegates that point directly at the target method, avoiding an intermediate closure
+
+
discard pattern in use binding
捨棄使用繫結中的模式
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs
new file mode 100644
index 00000000000..b0d991a9b7f
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs
@@ -0,0 +1,42 @@
+module DelegateCustomType
+
+open System
+
+// Custom, F#-declared delegate types exercise construction with delegates defined in the *compiled* assembly
+// (local scope, unlike imported BCL Func/Action) and with Invoke signatures the Func/Action tests do not
+// cover: a multi-argument (tupled) signature, a generic delegate, and a byref parameter. (F# forbids curried
+// delegate signatures — FS0950 — so every F# delegate has a single tupled Invoke parameter group.)
+
+type DTupled = delegate of int * int -> int
+type DGen<'T> = delegate of 'T -> 'T
+type DByref = delegate of byref -> unit
+
+let acc (x: int) (y: int) : int = x + y
+
+let ident (x: 'T) : 'T = x
+
+type C() =
+ member _.M (x: int) (y: int) : int = x * y
+
+// Tupled-signature custom delegate: Invoke(int, int).
+// 28. non-eta module function, custom delegate
+let tupledNonEta () = DTupled(acc)
+// 14. eta module function, custom delegate
+let tupledEta () = DTupled(fun a b -> acc a b)
+
+// Instance member through a custom delegate: the receiver becomes the delegate's Target.
+// 29. non-eta instance member, custom delegate
+let instanceNonEta (c: C) = DTupled(c.M)
+// 15. eta instance member, custom delegate
+let instanceEta (c: C) = DTupled(fun a b -> c.M a b)
+
+// Generic custom delegate instantiated at int: Invoke(int):int over the generic target.
+// 30. non-eta generic method, generic custom delegate
+let genNonEta () = DGen(ident)
+// 16. eta generic method, generic custom delegate
+let genEta () = DGen(fun x -> ident x)
+
+// byref-parameter custom delegate: the body mutates through the byref, so it is not a transparent forwarding
+// call and stays a closure. Documents that a byref Invoke parameter does not break the recognizer.
+// 53. byref-parameter delegate (mutating body)
+let byrefMutate () = DByref(fun x -> x <- x + 1)
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOff.Preview.il.bsl
new file mode 100644
index 00000000000..c9d56b7d0a0
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOff.Preview.il.bsl
@@ -0,0 +1,348 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable sealed nested public DTupled
+ extends [runtime]System.MulticastDelegate
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance int32 Invoke(int32 A_1, int32 A_2) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual
+ instance class [runtime]System.IAsyncResult
+ BeginInvoke(int32 A_1,
+ int32 A_2,
+ class [runtime]System.AsyncCallback callback,
+ object objects) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance int32 EndInvoke(class [runtime]System.IAsyncResult result) runtime managed
+ {
+ }
+
+ }
+
+ .class auto ansi serializable sealed nested public DGen`1
+ extends [runtime]System.MulticastDelegate
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance !T Invoke(!T A_1) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual
+ instance class [runtime]System.IAsyncResult
+ BeginInvoke(!T A_1,
+ class [runtime]System.AsyncCallback callback,
+ object objects) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance !T EndInvoke(class [runtime]System.IAsyncResult result) runtime managed
+ {
+ }
+
+ }
+
+ .class auto ansi serializable sealed nested public DByref
+ extends [runtime]System.MulticastDelegate
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance void Invoke(int32& A_1) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual
+ instance class [runtime]System.IAsyncResult
+ BeginInvoke(int32& A_1,
+ class [runtime]System.AsyncCallback callback,
+ object objects) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance void EndInvoke(class [runtime]System.IAsyncResult result) runtime managed
+ {
+ }
+
+ }
+
+ .class auto ansi serializable nested public C
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public specialname rtspecialname instance void .ctor() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ret
+ }
+
+ .method public hidebysig instance int32 M(int32 x, int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.1
+ IL_0001: ldarg.2
+ IL_0002: mul
+ IL_0003: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname tupledEta@25
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call int32 assembly::acc(int32,
+ int32)
+ IL_0007: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname instanceEta@31
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/C c
+ .method public specialname rtspecialname instance void .ctor(class assembly/C c) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/C assembly/instanceEta@31::c
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance int32 Invoke(int32 a, int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/C assembly/instanceEta@31::c
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: callvirt instance int32 assembly/C::M(int32,
+ int32)
+ IL_000d: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname genEta@37
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 x) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call !!0 assembly::ident(!!0)
+ IL_0006: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname byrefMutate@42
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32& x) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.0
+ IL_0002: ldobj [runtime]System.Int32
+ IL_0007: ldc.i4.1
+ IL_0008: add
+ IL_0009: stobj [runtime]System.Int32
+ IL_000e: ret
+ }
+
+ }
+
+ .method public static int32 acc(int32 x,
+ int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: add
+ IL_0003: ret
+ }
+
+ .method public static !!T ident(!!T x) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ret
+ }
+
+ .method public static class assembly/DTupled tupledNonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly::acc(int32,
+ int32)
+ IL_0007: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DTupled tupledEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/tupledEta@25::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DTupled instanceNonEta(class assembly/C c) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldftn instance int32 assembly/C::M(int32,
+ int32)
+ IL_0007: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DTupled instanceEta(class assembly/C c) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/instanceEta@31::.ctor(class assembly/C)
+ IL_0006: ldftn instance int32 assembly/instanceEta@31::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+ .method public static class assembly/DGen`1 genNonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn !!0 assembly::ident(!!0)
+ IL_0007: newobj instance void class assembly/DGen`1::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DGen`1 genEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/genEta@37::Invoke(int32)
+ IL_0007: newobj instance void class assembly/DGen`1::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DByref byrefMutate() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/byrefMutate@42::Invoke(int32&)
+ IL_0007: newobj instance void assembly/DByref::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOff.il.bsl
new file mode 100644
index 00000000000..66053083940
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOff.il.bsl
@@ -0,0 +1,414 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable sealed nested public DTupled
+ extends [runtime]System.MulticastDelegate
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance int32 Invoke(int32 A_1, int32 A_2) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual
+ instance class [runtime]System.IAsyncResult
+ BeginInvoke(int32 A_1,
+ int32 A_2,
+ class [runtime]System.AsyncCallback callback,
+ object objects) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance int32 EndInvoke(class [runtime]System.IAsyncResult result) runtime managed
+ {
+ }
+
+ }
+
+ .class auto ansi serializable sealed nested public DGen`1
+ extends [runtime]System.MulticastDelegate
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance !T Invoke(!T A_1) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual
+ instance class [runtime]System.IAsyncResult
+ BeginInvoke(!T A_1,
+ class [runtime]System.AsyncCallback callback,
+ object objects) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance !T EndInvoke(class [runtime]System.IAsyncResult result) runtime managed
+ {
+ }
+
+ }
+
+ .class auto ansi serializable sealed nested public DByref
+ extends [runtime]System.MulticastDelegate
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance void Invoke(int32& A_1) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual
+ instance class [runtime]System.IAsyncResult
+ BeginInvoke(int32& A_1,
+ class [runtime]System.AsyncCallback callback,
+ object objects) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance void EndInvoke(class [runtime]System.IAsyncResult result) runtime managed
+ {
+ }
+
+ }
+
+ .class auto ansi serializable nested public C
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public specialname rtspecialname instance void .ctor() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ret
+ }
+
+ .method public hidebysig instance int32 M(int32 x, int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.1
+ IL_0001: ldarg.2
+ IL_0002: mul
+ IL_0003: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname tupledNonEta@23
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 x,
+ int32 y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call int32 assembly::acc(int32,
+ int32)
+ IL_0007: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname tupledEta@25
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call int32 assembly::acc(int32,
+ int32)
+ IL_0007: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname instanceNonEta@29
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/C c
+ .method public specialname rtspecialname instance void .ctor(class assembly/C c) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/C assembly/instanceNonEta@29::c
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance int32 Invoke(int32 delegateArg0, int32 delegateArg1) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/C assembly/instanceNonEta@29::c
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: callvirt instance int32 assembly/C::M(int32,
+ int32)
+ IL_000d: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname instanceEta@31
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/C c
+ .method public specialname rtspecialname instance void .ctor(class assembly/C c) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/C assembly/instanceEta@31::c
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance int32 Invoke(int32 a, int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/C assembly/instanceEta@31::c
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: callvirt instance int32 assembly/C::M(int32,
+ int32)
+ IL_000d: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname genNonEta@35
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 delegateArg0) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call !!0 assembly::ident(!!0)
+ IL_0006: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname genEta@37
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 x) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call !!0 assembly::ident(!!0)
+ IL_0006: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname byrefMutate@42
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32& x) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.0
+ IL_0002: ldobj [runtime]System.Int32
+ IL_0007: ldc.i4.1
+ IL_0008: add
+ IL_0009: stobj [runtime]System.Int32
+ IL_000e: ret
+ }
+
+ }
+
+ .method public static int32 acc(int32 x,
+ int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: add
+ IL_0003: ret
+ }
+
+ .method public static !!T ident(!!T x) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ret
+ }
+
+ .method public static class assembly/DTupled tupledNonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/tupledNonEta@23::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DTupled tupledEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/tupledEta@25::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DTupled instanceNonEta(class assembly/C c) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/instanceNonEta@29::.ctor(class assembly/C)
+ IL_0006: ldftn instance int32 assembly/instanceNonEta@29::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+ .method public static class assembly/DTupled instanceEta(class assembly/C c) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/instanceEta@31::.ctor(class assembly/C)
+ IL_0006: ldftn instance int32 assembly/instanceEta@31::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+ .method public static class assembly/DGen`1 genNonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/genNonEta@35::Invoke(int32)
+ IL_0007: newobj instance void class assembly/DGen`1::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DGen`1 genEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/genEta@37::Invoke(int32)
+ IL_0007: newobj instance void class assembly/DGen`1::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DByref byrefMutate() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/byrefMutate@42::Invoke(int32&)
+ IL_0007: newobj instance void assembly/DByref::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOn.Preview.il.bsl
new file mode 100644
index 00000000000..15a1a5f9f34
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOn.Preview.il.bsl
@@ -0,0 +1,282 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable sealed nested public DTupled
+ extends [runtime]System.MulticastDelegate
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance int32 Invoke(int32 A_1, int32 A_2) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual
+ instance class [runtime]System.IAsyncResult
+ BeginInvoke(int32 A_1,
+ int32 A_2,
+ class [runtime]System.AsyncCallback callback,
+ object objects) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance int32 EndInvoke(class [runtime]System.IAsyncResult result) runtime managed
+ {
+ }
+
+ }
+
+ .class auto ansi serializable sealed nested public DGen`1
+ extends [runtime]System.MulticastDelegate
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance !T Invoke(!T A_1) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual
+ instance class [runtime]System.IAsyncResult
+ BeginInvoke(!T A_1,
+ class [runtime]System.AsyncCallback callback,
+ object objects) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance !T EndInvoke(class [runtime]System.IAsyncResult result) runtime managed
+ {
+ }
+
+ }
+
+ .class auto ansi serializable sealed nested public DByref
+ extends [runtime]System.MulticastDelegate
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance void Invoke(int32& A_1) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual
+ instance class [runtime]System.IAsyncResult
+ BeginInvoke(int32& A_1,
+ class [runtime]System.AsyncCallback callback,
+ object objects) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance void EndInvoke(class [runtime]System.IAsyncResult result) runtime managed
+ {
+ }
+
+ }
+
+ .class auto ansi serializable nested public C
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public specialname rtspecialname instance void .ctor() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ret
+ }
+
+ .method public hidebysig instance int32 M(int32 x, int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.1
+ IL_0001: ldarg.2
+ IL_0002: mul
+ IL_0003: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname byrefMutate@42
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32& x) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.0
+ IL_0002: ldobj [runtime]System.Int32
+ IL_0007: ldc.i4.1
+ IL_0008: add
+ IL_0009: stobj [runtime]System.Int32
+ IL_000e: ret
+ }
+
+ }
+
+ .method public static int32 acc(int32 x,
+ int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: add
+ IL_0003: ret
+ }
+
+ .method public static !!T ident(!!T x) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ret
+ }
+
+ .method public static class assembly/DTupled tupledNonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly::acc(int32,
+ int32)
+ IL_0007: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DTupled tupledEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly::acc(int32,
+ int32)
+ IL_0007: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DTupled instanceNonEta(class assembly/C c) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldftn instance int32 assembly/C::M(int32,
+ int32)
+ IL_0007: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DTupled instanceEta(class assembly/C c) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldftn instance int32 assembly/C::M(int32,
+ int32)
+ IL_0007: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DGen`1 genNonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn !!0 assembly::ident(!!0)
+ IL_0007: newobj instance void class assembly/DGen`1::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DGen`1 genEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn !!0 assembly::ident(!!0)
+ IL_0007: newobj instance void class assembly/DGen`1::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DByref byrefMutate() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/byrefMutate@42::Invoke(int32&)
+ IL_0007: newobj instance void assembly/DByref::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOn.il.bsl
new file mode 100644
index 00000000000..91f76166944
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateCustomType.fs.OptimizeOn.il.bsl
@@ -0,0 +1,378 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable sealed nested public DTupled
+ extends [runtime]System.MulticastDelegate
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance int32 Invoke(int32 A_1, int32 A_2) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual
+ instance class [runtime]System.IAsyncResult
+ BeginInvoke(int32 A_1,
+ int32 A_2,
+ class [runtime]System.AsyncCallback callback,
+ object objects) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance int32 EndInvoke(class [runtime]System.IAsyncResult result) runtime managed
+ {
+ }
+
+ }
+
+ .class auto ansi serializable sealed nested public DGen`1
+ extends [runtime]System.MulticastDelegate
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance !T Invoke(!T A_1) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual
+ instance class [runtime]System.IAsyncResult
+ BeginInvoke(!T A_1,
+ class [runtime]System.AsyncCallback callback,
+ object objects) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance !T EndInvoke(class [runtime]System.IAsyncResult result) runtime managed
+ {
+ }
+
+ }
+
+ .class auto ansi serializable sealed nested public DByref
+ extends [runtime]System.MulticastDelegate
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance void Invoke(int32& A_1) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual
+ instance class [runtime]System.IAsyncResult
+ BeginInvoke(int32& A_1,
+ class [runtime]System.AsyncCallback callback,
+ object objects) runtime managed
+ {
+ }
+
+ .method public hidebysig strict virtual instance void EndInvoke(class [runtime]System.IAsyncResult result) runtime managed
+ {
+ }
+
+ }
+
+ .class auto ansi serializable nested public C
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public specialname rtspecialname instance void .ctor() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ret
+ }
+
+ .method public hidebysig instance int32 M(int32 x, int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.1
+ IL_0001: ldarg.2
+ IL_0002: mul
+ IL_0003: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname tupledNonEta@23
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 x,
+ int32 y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: add
+ IL_0003: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname tupledEta@25
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: add
+ IL_0003: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname instanceNonEta@29
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 delegateArg0,
+ int32 delegateArg1) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: mul
+ IL_0003: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname instanceEta@31
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: mul
+ IL_0003: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname genNonEta@35
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 delegateArg0) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname genEta@37
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 x) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname byrefMutate@42
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32& x) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.0
+ IL_0002: ldobj [runtime]System.Int32
+ IL_0007: ldc.i4.1
+ IL_0008: add
+ IL_0009: stobj [runtime]System.Int32
+ IL_000e: ret
+ }
+
+ }
+
+ .method public static int32 acc(int32 x,
+ int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: add
+ IL_0003: ret
+ }
+
+ .method public static !!T ident(!!T x) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ret
+ }
+
+ .method public static class assembly/DTupled tupledNonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/tupledNonEta@23::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DTupled tupledEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/tupledEta@25::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DTupled instanceNonEta(class assembly/C c) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/instanceNonEta@29::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DTupled instanceEta(class assembly/C c) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/instanceEta@31::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void assembly/DTupled::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DGen`1 genNonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/genNonEta@35::Invoke(int32)
+ IL_0007: newobj instance void class assembly/DGen`1::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DGen`1 genEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/genEta@37::Invoke(int32)
+ IL_0007: newobj instance void class assembly/DGen`1::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class assembly/DByref byrefMutate() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/byrefMutate@42::Invoke(int32&)
+ IL_0007: newobj instance void assembly/DByref::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs
new file mode 100644
index 00000000000..6d7ecdd9960
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs
@@ -0,0 +1,22 @@
+module DelegateExtensionMethod
+
+open System
+open System.Runtime.CompilerServices
+
+type Holder() =
+ class
+ end
+
+[]
+type HolderExtensions =
+ []
+ static member Combine (h: Holder, x: int, y: int) : int = x + y
+
+// An extension member compiles to a static method whose first parameter is the receiver. Using it as a
+// delegate target binds that receiver as a leading argument, which the CLR's "closed over the first argument"
+// delegate stores as the Target while the function pointer points at the static method - a direct delegate.
+// (The member here is tupled, 'Combine(h, x, y)'; the recognizer de-tuples the forwarding call by the target's
+// arity, exactly as the code generator does when emitting the call.) As an eta-expanded delegate it is direct
+// only in optimized builds, where the user's lambda need not survive for debugging.
+// 52. extension member (receiver is a leading static arg, bound as Target)
+let extensionEta (h: Holder) = Func(fun a b -> h.Combine(a, b))
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOff.Preview.il.bsl
new file mode 100644
index 00000000000..0e4b863938b
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOff.Preview.il.bsl
@@ -0,0 +1,138 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public Holder
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public specialname rtspecialname instance void .ctor() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ret
+ }
+
+ }
+
+ .class auto ansi serializable nested public HolderExtensions
+ extends [runtime]System.Object
+ {
+ .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public static int32 Combine(class assembly/Holder h,
+ int32 x,
+ int32 y) cil managed
+ {
+ .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.1
+ IL_0001: ldarg.2
+ IL_0002: add
+ IL_0003: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname extensionEta@22
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/Holder h
+ .method public specialname rtspecialname instance void .ctor(class assembly/Holder h) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/Holder assembly/extensionEta@22::h
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance int32 Invoke(int32 a, int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/Holder assembly/extensionEta@22::h
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: call int32 assembly/HolderExtensions::Combine(class assembly/Holder,
+ int32,
+ int32)
+ IL_000d: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Func`3 extensionEta(class assembly/Holder h) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/extensionEta@22::.ctor(class assembly/Holder)
+ IL_0006: ldftn instance int32 assembly/extensionEta@22::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void class [runtime]System.Func`3::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOff.il.bsl
new file mode 100644
index 00000000000..940811fcfab
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOff.il.bsl
@@ -0,0 +1,138 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public Holder
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public specialname rtspecialname instance void .ctor() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ret
+ }
+
+ }
+
+ .class auto ansi serializable nested public HolderExtensions
+ extends [runtime]System.Object
+ {
+ .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public static int32 Combine(class assembly/Holder h,
+ int32 x,
+ int32 y) cil managed
+ {
+ .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.1
+ IL_0001: ldarg.2
+ IL_0002: add
+ IL_0003: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname extensionEta@22
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/Holder h
+ .method public specialname rtspecialname instance void .ctor(class assembly/Holder h) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/Holder assembly/extensionEta@22::h
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance int32 Invoke(int32 a, int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/Holder assembly/extensionEta@22::h
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: call int32 assembly/HolderExtensions::Combine(class assembly/Holder,
+ int32,
+ int32)
+ IL_000d: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Func`3 extensionEta(class assembly/Holder h) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/extensionEta@22::.ctor(class assembly/Holder)
+ IL_0006: ldftn instance int32 assembly/extensionEta@22::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void class [runtime]System.Func`3::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOn.Preview.il.bsl
new file mode 100644
index 00000000000..6e78d1cdc46
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOn.Preview.il.bsl
@@ -0,0 +1,105 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public Holder
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public specialname rtspecialname instance void .ctor() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ret
+ }
+
+ }
+
+ .class auto ansi serializable nested public HolderExtensions
+ extends [runtime]System.Object
+ {
+ .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public static int32 Combine(class assembly/Holder h,
+ int32 x,
+ int32 y) cil managed
+ {
+ .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.1
+ IL_0001: ldarg.2
+ IL_0002: add
+ IL_0003: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Func`3 extensionEta(class assembly/Holder h) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldftn int32 assembly/HolderExtensions::Combine(class assembly/Holder,
+ int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOn.il.bsl
new file mode 100644
index 00000000000..8168284b0b3
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateExtensionMethod.fs.OptimizeOn.il.bsl
@@ -0,0 +1,121 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public Holder
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public specialname rtspecialname instance void .ctor() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ret
+ }
+
+ }
+
+ .class auto ansi serializable nested public HolderExtensions
+ extends [runtime]System.Object
+ {
+ .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public static int32 Combine(class assembly/Holder h,
+ int32 x,
+ int32 y) cil managed
+ {
+ .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.1
+ IL_0001: ldarg.2
+ IL_0002: add
+ IL_0003: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname extensionEta@22
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: add
+ IL_0003: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Func`3 extensionEta(class assembly/Holder h) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/extensionEta@22::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs
new file mode 100644
index 00000000000..535bee3d582
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs
@@ -0,0 +1,13 @@
+module DelegateGenericInstanceMethod
+
+open System
+
+type C() =
+ member _.IMc<'T> (x: 'T) (y: 'T) : unit = ()
+ member _.IMt<'T> (x: 'T, y: 'T) : unit = ()
+
+// 5. eta generic instance method (curried application)
+let case5_etaCurried (o: C) = Action(fun a b -> o.IMc a b)
+
+// 35. eta generic instance method, tupled application
+let case35_etaTupled (o: C) = Action(fun a b -> o.IMt(a, b))
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOff.Preview.il.bsl
new file mode 100644
index 00000000000..12696733399
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOff.Preview.il.bsl
@@ -0,0 +1,179 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public C
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public specialname rtspecialname instance void .ctor() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ret
+ }
+
+ .method public hidebysig instance void IMc(!!T x, !!T y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public hidebysig instance void IMt(!!T x, !!T y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname case5_etaCurried@10
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/C o
+ .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/C assembly/case5_etaCurried@10::o
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/C assembly/case5_etaCurried@10::o
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: callvirt instance void assembly/C::IMc(!!0,
+ !!0)
+ IL_000d: nop
+ IL_000e: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname case35_etaTupled@13
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/C o
+ .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/C assembly/case35_etaTupled@13::o
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/C assembly/case35_etaTupled@13::o
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: callvirt instance void assembly/C::IMt(!!0,
+ !!0)
+ IL_000d: nop
+ IL_000e: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Action`2 case5_etaCurried(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/case5_etaCurried@10::.ctor(class assembly/C)
+ IL_0006: ldftn instance void assembly/case5_etaCurried@10::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case35_etaTupled(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/case35_etaTupled@13::.ctor(class assembly/C)
+ IL_0006: ldftn instance void assembly/case35_etaTupled@13::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOff.il.bsl
new file mode 100644
index 00000000000..12696733399
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOff.il.bsl
@@ -0,0 +1,179 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public C
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public specialname rtspecialname instance void .ctor() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ret
+ }
+
+ .method public hidebysig instance void IMc(!!T x, !!T y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public hidebysig instance void IMt(!!T x, !!T y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname case5_etaCurried@10
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/C o
+ .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/C assembly/case5_etaCurried@10::o
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/C assembly/case5_etaCurried@10::o
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: callvirt instance void assembly/C::IMc(!!0,
+ !!0)
+ IL_000d: nop
+ IL_000e: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname case35_etaTupled@13
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/C o
+ .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/C assembly/case35_etaTupled@13::o
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/C assembly/case35_etaTupled@13::o
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: callvirt instance void assembly/C::IMt(!!0,
+ !!0)
+ IL_000d: nop
+ IL_000e: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Action`2 case5_etaCurried(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/case5_etaCurried@10::.ctor(class assembly/C)
+ IL_0006: ldftn instance void assembly/case5_etaCurried@10::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case35_etaTupled(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/case35_etaTupled@13::.ctor(class assembly/C)
+ IL_0006: ldftn instance void assembly/case35_etaTupled@13::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOn.Preview.il.bsl
new file mode 100644
index 00000000000..26e0b7e9705
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOn.Preview.il.bsl
@@ -0,0 +1,111 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public C
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public specialname rtspecialname instance void .ctor() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ret
+ }
+
+ .method public hidebysig instance void IMc(!!T x, !!T y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public hidebysig instance void IMt(!!T x, !!T y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Action`2 case5_etaCurried(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldftn instance void assembly/C::IMc(!!0,
+ !!0)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case35_etaTupled(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldftn instance void assembly/C::IMt(!!0,
+ !!0)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOn.il.bsl
new file mode 100644
index 00000000000..74be77228f1
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericInstanceMethod.fs.OptimizeOn.il.bsl
@@ -0,0 +1,139 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public C
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public specialname rtspecialname instance void .ctor() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ret
+ }
+
+ .method public hidebysig instance void IMc(!!T x, !!T y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public hidebysig instance void IMt(!!T x, !!T y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case5_etaCurried@10
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case35_etaTupled@13
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Action`2 case5_etaCurried(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case5_etaCurried@10::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case35_etaTupled(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case35_etaTupled@13::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs
new file mode 100644
index 00000000000..a4e30bdaf08
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs
@@ -0,0 +1,16 @@
+module DelegateGenericStaticMethod
+
+open System
+
+type G<'U> =
+ static member SMc<'T> (x: 'T) (y: 'T) : unit = ()
+ static member SMt<'T> (x: 'T, y: 'T) : unit = ()
+
+// 19. non-eta generic static method (generic type + generic method)
+let case19_nonEta () = Action(G.SMc)
+
+// 3. eta generic static method (curried application)
+let case3_etaCurried () = Action(fun a b -> G.SMc a b)
+
+// 33. eta generic static method, tupled application
+let case33_etaTupled () = Action(fun a b -> G.SMt(a, b))
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOff.Preview.il.bsl
new file mode 100644
index 00000000000..39cb26442a6
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOff.Preview.il.bsl
@@ -0,0 +1,152 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public G`1
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public static void SMc(!!T x,
+ !!T y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static void SMt(!!T x,
+ !!T y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case3_etaCurried@13
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call void class assembly/G`1::SMc(!!0,
+ !!0)
+ IL_0007: nop
+ IL_0008: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case33_etaTupled@16
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call void class assembly/G`1::SMt(!!0,
+ !!0)
+ IL_0007: nop
+ IL_0008: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Action`2 case19_nonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void class assembly/G`1::SMc(!!0,
+ !!0)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case3_etaCurried() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case3_etaCurried@13::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case33_etaTupled() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case33_etaTupled@16::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOff.il.bsl
new file mode 100644
index 00000000000..52f0ce42863
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOff.il.bsl
@@ -0,0 +1,171 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public G`1
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public static void SMc(!!T x,
+ !!T y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static void SMt(!!T x,
+ !!T y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case19_nonEta@10
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 x,
+ int32 y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call void class assembly/G`1::SMc(!!0,
+ !!0)
+ IL_0007: nop
+ IL_0008: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case3_etaCurried@13
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call void class assembly/G`1::SMc(!!0,
+ !!0)
+ IL_0007: nop
+ IL_0008: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case33_etaTupled@16
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call void class assembly/G`1::SMt(!!0,
+ !!0)
+ IL_0007: nop
+ IL_0008: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Action`2 case19_nonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case19_nonEta@10::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case3_etaCurried() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case3_etaCurried@13::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case33_etaTupled() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case33_etaTupled@16::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOn.Preview.il.bsl
new file mode 100644
index 00000000000..cb158381c58
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOn.Preview.il.bsl
@@ -0,0 +1,114 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public G`1
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public static void SMc(!!T x,
+ !!T y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static void SMt(!!T x,
+ !!T y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Action`2 case19_nonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void class assembly/G`1::SMc(!!0,
+ !!0)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case3_etaCurried() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void class assembly/G`1::SMc(!!0,
+ !!0)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case33_etaTupled() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void class assembly/G`1::SMt(!!0,
+ !!0)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOn.il.bsl
new file mode 100644
index 00000000000..97f8c55b9dc
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateGenericStaticMethod.fs.OptimizeOn.il.bsl
@@ -0,0 +1,156 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public G`1
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .method public static void SMc(!!T x,
+ !!T y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static void SMt(!!T x,
+ !!T y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case19_nonEta@10
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 x,
+ int32 y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case3_etaCurried@13
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case33_etaTupled@16
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Action`2 case19_nonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case19_nonEta@10::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case3_etaCurried() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case3_etaCurried@13::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case33_etaTupled() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case33_etaTupled@16::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs
new file mode 100644
index 00000000000..d5a9ebf9fbe
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs
@@ -0,0 +1,15 @@
+module DelegateILMethod
+
+open System
+open System.Text
+
+// IL (BCL) method targets are compiled as TOp.ILCall rather than an F# value application. They are made
+// direct only in optimized builds; in unoptimized builds the eta form keeps a closure (matching the F#
+// eta policy). See DelegateKnownFunction for the F#-value equivalent.
+
+// 12. eta IL/BCL static method (System.Math.Max).
+let ilStaticEta () = Func(fun a b -> Math.Max(a, b))
+
+// 13. eta IL/BCL instance method (StringBuilder.Append(string)) on a reference type. The receiver is a
+// parameter, evaluated at the construction site and carried as the delegate's Target.
+let ilInstanceEta (sb: StringBuilder) = Func(fun s -> sb.Append(s))
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOff.Preview.il.bsl
new file mode 100644
index 00000000000..5ca457d058f
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOff.Preview.il.bsl
@@ -0,0 +1,127 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname ilStaticEta@11
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call int32 [runtime]System.Math::Max(int32,
+ int32)
+ IL_0007: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname ilInstanceEta@15
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class [runtime]System.Text.StringBuilder sb
+ .method public specialname rtspecialname instance void .ctor(class [runtime]System.Text.StringBuilder sb) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::sb
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance class [runtime]System.Text.StringBuilder Invoke(string s) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::sb
+ IL_0006: ldarg.1
+ IL_0007: callvirt instance class [runtime]System.Text.StringBuilder [runtime]System.Text.StringBuilder::Append(string)
+ IL_000c: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Func`3 ilStaticEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/ilStaticEta@11::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Func`2 ilInstanceEta(class [runtime]System.Text.StringBuilder sb) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/ilInstanceEta@15::.ctor(class [runtime]System.Text.StringBuilder)
+ IL_0006: ldftn instance class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::Invoke(string)
+ IL_000c: newobj instance void class [runtime]System.Func`2::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOff.il.bsl
new file mode 100644
index 00000000000..98e340a1d79
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOff.il.bsl
@@ -0,0 +1,127 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname ilStaticEta@11
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call int32 [runtime]System.Math::Max(int32,
+ int32)
+ IL_0007: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname ilInstanceEta@15
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class [runtime]System.Text.StringBuilder sb
+ .method public specialname rtspecialname instance void .ctor(class [runtime]System.Text.StringBuilder sb) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::sb
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance class [runtime]System.Text.StringBuilder Invoke(string s) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::sb
+ IL_0006: ldarg.1
+ IL_0007: callvirt instance class [runtime]System.Text.StringBuilder [runtime]System.Text.StringBuilder::Append(string)
+ IL_000c: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Func`3 ilStaticEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/ilStaticEta@11::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Func`2 ilInstanceEta(class [runtime]System.Text.StringBuilder sb) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/ilInstanceEta@15::.ctor(class [runtime]System.Text.StringBuilder)
+ IL_0006: ldftn instance class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::Invoke(string)
+ IL_000c: newobj instance void class [runtime]System.Func`2::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOn.Preview.il.bsl
new file mode 100644
index 00000000000..ef4e95130a2
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOn.Preview.il.bsl
@@ -0,0 +1,78 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .method public static class [runtime]System.Func`3 ilStaticEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 [runtime]System.Math::Max(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Func`2 ilInstanceEta(class [runtime]System.Text.StringBuilder sb) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldftn instance class [runtime]System.Text.StringBuilder [runtime]System.Text.StringBuilder::Append(string)
+ IL_0007: newobj instance void class [runtime]System.Func`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOn.il.bsl
new file mode 100644
index 00000000000..98e340a1d79
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateILMethod.fs.OptimizeOn.il.bsl
@@ -0,0 +1,127 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname ilStaticEta@11
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static int32 Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call int32 [runtime]System.Math::Max(int32,
+ int32)
+ IL_0007: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname ilInstanceEta@15
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class [runtime]System.Text.StringBuilder sb
+ .method public specialname rtspecialname instance void .ctor(class [runtime]System.Text.StringBuilder sb) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::sb
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance class [runtime]System.Text.StringBuilder Invoke(string s) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::sb
+ IL_0006: ldarg.1
+ IL_0007: callvirt instance class [runtime]System.Text.StringBuilder [runtime]System.Text.StringBuilder::Append(string)
+ IL_000c: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Func`3 ilStaticEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn int32 assembly/ilStaticEta@11::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Func`3::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Func`2 ilInstanceEta(class [runtime]System.Text.StringBuilder sb) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/ilInstanceEta@15::.ctor(class [runtime]System.Text.StringBuilder)
+ IL_0006: ldftn instance class [runtime]System.Text.StringBuilder assembly/ilInstanceEta@15::Invoke(string)
+ IL_000c: newobj instance void class [runtime]System.Func`2::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs
new file mode 100644
index 00000000000..76c6c53e334
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs
@@ -0,0 +1,21 @@
+module DelegateInstanceMethod
+
+open System
+
+type C(k: int) =
+ member _.AddC (x: int) (y: int) : unit = ignore k
+ member _.AddT (x: int, y: int) : unit = ignore k
+ abstract V : int -> int -> unit
+ default _.V (x: int) (y: int) : unit = ignore k
+
+// 20. non-eta instance method
+let case20_nonEta (o: C) = Action(o.AddC)
+
+// 4. eta instance method (curried application)
+let case4_etaCurried (o: C) = Action(fun a b -> o.AddC a b)
+
+// 34. eta instance method, tupled application
+let case34_etaTupled (o: C) = Action(fun a b -> o.AddT(a, b))
+
+// 21. non-eta virtual instance method: a direct delegate must use ldvirtftn (with dup) to preserve dispatch
+let case21_virtual (o: C) = Action(o.V)
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOff.Preview.il.bsl
new file mode 100644
index 00000000000..876f6a1aaee
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOff.Preview.il.bsl
@@ -0,0 +1,228 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public C
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .field assembly int32 k
+ .method public specialname rtspecialname instance void .ctor(int32 k) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ldarg.0
+ IL_0009: ldarg.1
+ IL_000a: stfld int32 assembly/C::k
+ IL_000f: ret
+ }
+
+ .method public hidebysig instance void AddC(int32 x, int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 3
+ .locals init (int32 V_0)
+ IL_0000: ldarg.0
+ IL_0001: ldfld int32 assembly/C::k
+ IL_0006: stloc.0
+ IL_0007: ret
+ }
+
+ .method public hidebysig instance void AddT(int32 x, int32 y) cil managed
+ {
+
+ .maxstack 3
+ .locals init (int32 V_0)
+ IL_0000: ldarg.0
+ IL_0001: ldfld int32 assembly/C::k
+ IL_0006: stloc.0
+ IL_0007: ret
+ }
+
+ .method public hidebysig virtual instance void V(int32 x, int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 3
+ .locals init (int32 V_0)
+ IL_0000: ldarg.0
+ IL_0001: ldfld int32 assembly/C::k
+ IL_0006: stloc.0
+ IL_0007: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname case4_etaCurried@15
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/C o
+ .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/C assembly/case4_etaCurried@15::o
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/C assembly/case4_etaCurried@15::o
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: callvirt instance void assembly/C::AddC(int32,
+ int32)
+ IL_000d: nop
+ IL_000e: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname case34_etaTupled@18
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/C o
+ .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/C assembly/case34_etaTupled@18::o
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/C assembly/case34_etaTupled@18::o
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: callvirt instance void assembly/C::AddT(int32,
+ int32)
+ IL_000d: nop
+ IL_000e: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Action`2 case20_nonEta(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldftn instance void assembly/C::AddC(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case4_etaCurried(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/case4_etaCurried@15::.ctor(class assembly/C)
+ IL_0006: ldftn instance void assembly/case4_etaCurried@15::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case34_etaTupled(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/case34_etaTupled@18::.ctor(class assembly/C)
+ IL_0006: ldftn instance void assembly/case34_etaTupled@18::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case21_virtual(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: dup
+ IL_0002: ldvirtftn instance void assembly/C::V(int32,
+ int32)
+ IL_0008: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000d: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOff.il.bsl
new file mode 100644
index 00000000000..a9c6bfae607
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOff.il.bsl
@@ -0,0 +1,295 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public C
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .field assembly int32 k
+ .method public specialname rtspecialname instance void .ctor(int32 k) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ldarg.0
+ IL_0009: ldarg.1
+ IL_000a: stfld int32 assembly/C::k
+ IL_000f: ret
+ }
+
+ .method public hidebysig instance void AddC(int32 x, int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 3
+ .locals init (int32 V_0)
+ IL_0000: ldarg.0
+ IL_0001: ldfld int32 assembly/C::k
+ IL_0006: stloc.0
+ IL_0007: ret
+ }
+
+ .method public hidebysig instance void AddT(int32 x, int32 y) cil managed
+ {
+
+ .maxstack 3
+ .locals init (int32 V_0)
+ IL_0000: ldarg.0
+ IL_0001: ldfld int32 assembly/C::k
+ IL_0006: stloc.0
+ IL_0007: ret
+ }
+
+ .method public hidebysig virtual instance void V(int32 x, int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 3
+ .locals init (int32 V_0)
+ IL_0000: ldarg.0
+ IL_0001: ldfld int32 assembly/C::k
+ IL_0006: stloc.0
+ IL_0007: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname case20_nonEta@12
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/C o
+ .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/C assembly/case20_nonEta@12::o
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance void Invoke(int32 delegateArg0, int32 delegateArg1) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/C assembly/case20_nonEta@12::o
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: callvirt instance void assembly/C::AddC(int32,
+ int32)
+ IL_000d: nop
+ IL_000e: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname case4_etaCurried@15
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/C o
+ .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/C assembly/case4_etaCurried@15::o
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/C assembly/case4_etaCurried@15::o
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: callvirt instance void assembly/C::AddC(int32,
+ int32)
+ IL_000d: nop
+ IL_000e: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname case34_etaTupled@18
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/C o
+ .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/C assembly/case34_etaTupled@18::o
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance void Invoke(int32 a, int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/C assembly/case34_etaTupled@18::o
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: callvirt instance void assembly/C::AddT(int32,
+ int32)
+ IL_000d: nop
+ IL_000e: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname case21_virtual@21
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/C o
+ .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/C assembly/case21_virtual@21::o
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance void Invoke(int32 delegateArg0, int32 delegateArg1) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/C assembly/case21_virtual@21::o
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: tail.
+ IL_000a: callvirt instance void assembly/C::V(int32,
+ int32)
+ IL_000f: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Action`2 case20_nonEta(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/case20_nonEta@12::.ctor(class assembly/C)
+ IL_0006: ldftn instance void assembly/case20_nonEta@12::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case4_etaCurried(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/case4_etaCurried@15::.ctor(class assembly/C)
+ IL_0006: ldftn instance void assembly/case4_etaCurried@15::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case34_etaTupled(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/case34_etaTupled@18::.ctor(class assembly/C)
+ IL_0006: ldftn instance void assembly/case34_etaTupled@18::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case21_virtual(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/case21_virtual@21::.ctor(class assembly/C)
+ IL_0006: ldftn instance void assembly/case21_virtual@21::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOn.Preview.il.bsl
new file mode 100644
index 00000000000..13e7184f77c
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOn.Preview.il.bsl
@@ -0,0 +1,148 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public C
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .field assembly int32 k
+ .method public specialname rtspecialname instance void .ctor(int32 k) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ldarg.0
+ IL_0009: ldarg.1
+ IL_000a: stfld int32 assembly/C::k
+ IL_000f: ret
+ }
+
+ .method public hidebysig instance void AddC(int32 x, int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public hidebysig instance void AddT(int32 x, int32 y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public hidebysig virtual instance void V(int32 x, int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Action`2 case20_nonEta(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldftn instance void assembly/C::AddC(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case4_etaCurried(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldftn instance void assembly/C::AddC(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case34_etaTupled(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldftn instance void assembly/C::AddT(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case21_virtual(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: dup
+ IL_0002: ldvirtftn instance void assembly/C::V(int32,
+ int32)
+ IL_0008: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000d: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOn.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOn.il.bsl
new file mode 100644
index 00000000000..b3569cf1a24
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateInstanceMethod.fs.OptimizeOn.il.bsl
@@ -0,0 +1,223 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class auto ansi serializable nested public C
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
+ .field assembly int32 k
+ .method public specialname rtspecialname instance void .ctor(int32 k) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: callvirt instance void [runtime]System.Object::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: pop
+ IL_0008: ldarg.0
+ IL_0009: ldarg.1
+ IL_000a: stfld int32 assembly/C::k
+ IL_000f: ret
+ }
+
+ .method public hidebysig instance void AddC(int32 x, int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public hidebysig instance void AddT(int32 x, int32 y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public hidebysig virtual instance void V(int32 x, int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case20_nonEta@12
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 delegateArg0,
+ int32 delegateArg1) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case4_etaCurried@15
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case34_etaTupled@18
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .class auto autochar serializable sealed nested assembly beforefieldinit specialname case21_virtual@21
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .field public class assembly/C o
+ .method public specialname rtspecialname instance void .ctor(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: stfld class assembly/C assembly/case21_virtual@21::o
+ IL_0007: ldarg.0
+ IL_0008: call instance void [runtime]System.Object::.ctor()
+ IL_000d: ret
+ }
+
+ .method assembly hidebysig instance void Invoke(int32 delegateArg0, int32 delegateArg1) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldfld class assembly/C assembly/case21_virtual@21::o
+ IL_0006: ldarg.1
+ IL_0007: ldarg.2
+ IL_0008: tail.
+ IL_000a: callvirt instance void assembly/C::V(int32,
+ int32)
+ IL_000f: ret
+ }
+
+ }
+
+ .method public static class [runtime]System.Action`2 case20_nonEta(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case20_nonEta@12::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case4_etaCurried(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case4_etaCurried@15::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case34_etaTupled(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case34_etaTupled@18::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case21_virtual(class assembly/C o) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: newobj instance void assembly/case21_virtual@21::.ctor(class assembly/C)
+ IL_0006: ldftn instance void assembly/case21_virtual@21::Invoke(int32,
+ int32)
+ IL_000c: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_0011: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs
new file mode 100644
index 00000000000..8e550999ddf
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs
@@ -0,0 +1,20 @@
+module DelegateKnownFunction
+
+open System
+
+// known F# functions compiled as methods
+let handlerCurried (x: int) (y: int) : unit = ()
+let handlerTupled (x: int, y: int) : unit = ()
+let handler3 (x: int) (y: int) (z: int) : unit = ()
+
+// 17. non-eta module function
+let case17_nonEta () = Action(handlerCurried)
+
+// 1. eta module function (curried application)
+let case1_etaCurried () = Action(fun a b -> handlerCurried a b)
+
+// 31. eta module function, tupled application (same compiled representation)
+let case31_etaTupled () = Action(fun a b -> handlerTupled (a, b))
+
+// 37. partial application of module function (constant arg)
+let case37_partial () = Action(handler3 1)
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOff.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOff.Preview.il.bsl
new file mode 100644
index 00000000000..dd1c081a62f
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOff.Preview.il.bsl
@@ -0,0 +1,190 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case1_etaCurried@14
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call void assembly::handlerCurried(int32,
+ int32)
+ IL_0007: nop
+ IL_0008: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case31_etaTupled@17
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call void assembly::handlerTupled(int32,
+ int32)
+ IL_0007: nop
+ IL_0008: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case37_partial@20
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 arg1,
+ int32 arg2) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldc.i4.1
+ IL_0001: ldarg.0
+ IL_0002: ldarg.1
+ IL_0003: call void assembly::handler3(int32,
+ int32,
+ int32)
+ IL_0008: nop
+ IL_0009: ret
+ }
+
+ }
+
+ .method public static void handlerCurried(int32 x,
+ int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static void handlerTupled(int32 x,
+ int32 y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static void handler3(int32 x,
+ int32 y,
+ int32 z) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00
+ 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case17_nonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly::handlerCurried(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case1_etaCurried() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case1_etaCurried@14::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case31_etaTupled() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case31_etaTupled@17::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case37_partial() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case37_partial@20::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOff.il.bsl
new file mode 100644
index 00000000000..4d080c7c4a9
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOff.il.bsl
@@ -0,0 +1,209 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case17_nonEta@11
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 x,
+ int32 y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call void assembly::handlerCurried(int32,
+ int32)
+ IL_0007: nop
+ IL_0008: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case1_etaCurried@14
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call void assembly::handlerCurried(int32,
+ int32)
+ IL_0007: nop
+ IL_0008: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case31_etaTupled@17
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 a,
+ int32 b) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldarg.1
+ IL_0002: call void assembly::handlerTupled(int32,
+ int32)
+ IL_0007: nop
+ IL_0008: ret
+ }
+
+ }
+
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case37_partial@20
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 delegateArg0,
+ int32 delegateArg1) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldc.i4.1
+ IL_0001: ldarg.0
+ IL_0002: ldarg.1
+ IL_0003: call void assembly::handler3(int32,
+ int32,
+ int32)
+ IL_0008: nop
+ IL_0009: ret
+ }
+
+ }
+
+ .method public static void handlerCurried(int32 x,
+ int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static void handlerTupled(int32 x,
+ int32 y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static void handler3(int32 x,
+ int32 y,
+ int32 z) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00
+ 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case17_nonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case17_nonEta@11::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case1_etaCurried() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case1_etaCurried@14::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case31_etaTupled() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case31_etaTupled@17::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case37_partial() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case37_partial@20::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$assembly
+ extends [runtime]System.Object
+{
+ .method public static void main@() cil managed
+ {
+ .entrypoint
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOn.Preview.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOn.Preview.il.bsl
new file mode 100644
index 00000000000..d881a035d3d
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DirectDelegates/DelegateKnownFunction.fs.OptimizeOn.Preview.il.bsl
@@ -0,0 +1,145 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
+ int32,
+ int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
+
+
+
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.exe
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed assembly
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname case37_partial@20
+ extends [runtime]System.Object
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 )
+ .method assembly static void Invoke(int32 arg1,
+ int32 arg2) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ }
+
+ .method public static void handlerCurried(int32 x,
+ int32 y) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static void handlerTupled(int32 x,
+ int32 y) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static void handler3(int32 x,
+ int32 y,
+ int32 z) cil managed
+ {
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00
+ 00 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case17_nonEta() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly::handlerCurried(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case1_etaCurried() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly::handlerCurried(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case31_etaTupled() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly::handlerTupled(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2::.ctor(object,
+ native int)
+ IL_000c: ret
+ }
+
+ .method public static class [runtime]System.Action`2 case37_partial() cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ldnull
+ IL_0001: ldftn void assembly/case37_partial@20::Invoke(int32,
+ int32)
+ IL_0007: newobj instance void class [runtime]System.Action`2