diff --git a/src/Compiler/AbstractIL/ilwrite.fs b/src/Compiler/AbstractIL/ilwrite.fs index ecddf2460d8..9c6759ff5fb 100644 --- a/src/Compiler/AbstractIL/ilwrite.fs +++ b/src/Compiler/AbstractIL/ilwrite.fs @@ -1189,7 +1189,7 @@ let canGenPropertyDef cenv (prop: ILPropertyDef) = // If we have GetMethod or SetMethod set (i.e. not None), try and see if we have MethodDefs for them. // NOTE: They can be not-None and missing MethodDefs if we skip generating them for reference assembly in the earlier pass. // Only generate property if we have at least getter or setter, otherwise, we skip. - [| prop.GetMethod; prop.SetMethod |] + [| prop.GetMethod; prop.SetMethod |] |> Array.choose id |> Array.exists (MethodDefIdxExists cenv) @@ -1300,14 +1300,14 @@ and GenTypeDefPass2 pidx enc cenv (tdef: ILTypeDef) = // Now generate or assign index numbers for tables referenced by the maps. // Don't yet generate contents of these tables - leave that to pass3, as // code may need to embed these entries. - tdef.Implements |> List.iter (GenImplementsPass2 cenv env tidx) - events |> List.iter (GenEventDefPass2 cenv tidx) + tdef.Implements |> List.iter (GenImplementsPass2 cenv env tidx) tdef.Fields.AsList() |> List.iter (GenFieldDefPass2 tdef cenv tidx) tdef.Methods |> Seq.iter (GenMethodDefPass2 tdef cenv tidx) - // Generation of property definitions for **ref assemblies** is checking existence of generated method definitions. + // Generation of property & event definitions for **ref assemblies** is checking existence of generated method definitions. // Therefore, due to mutable state within "cenv", order of operations matters. // Who could have thought that using shared mutable state can bring unexpected bugs...? props |> List.iter (GenPropertyDefPass2 cenv tidx) + events |> List.iter (GenEventDefPass2 cenv tidx) tdef.NestedTypes.AsList() |> GenTypeDefsPass2 tidx (enc@[tdef.Name]) cenv with exn -> failwith ("Error in pass2 for type "+tdef.Name+", error: " + exn.Message) diff --git a/tests/fsharp/Compiler/CodeGen/EmittedIL/ReferenceAssemblyTests.fs b/tests/fsharp/Compiler/CodeGen/EmittedIL/ReferenceAssemblyTests.fs index 6857564db00..a50daae27fc 100644 --- a/tests/fsharp/Compiler/CodeGen/EmittedIL/ReferenceAssemblyTests.fs +++ b/tests/fsharp/Compiler/CodeGen/EmittedIL/ReferenceAssemblyTests.fs @@ -607,6 +607,104 @@ extends [runtime]System.Object }"""] + [] + let ``Cli events are emitted even for CliEvent members which are not last in a file`` () = + FSharp """ +module LibraryWithTwoClassesAndTwoEvents +open System + +let event = new DelegateEvent>() +type MyClass() = + [] + member this.EventFromFirstType = event.Publish + +let event2 = new DelegateEvent>() +type MyClass2() = + [] + member this.EventFromSecondType = event2.Publish +""" + |> withOptions ["--refonly"] + |> compile + |> shouldSucceed + |> verifyIL [ + referenceAssemblyAttributeExpectedIL + """.class auto ansi serializable nested public MyClass + 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: ldnull + IL_0001: throw +} + +.method public hidebysig specialname + instance void add_EventFromFirstType(class [runtime]System.EventHandler`1 'handler') cil managed +{ + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw +} + +.method public hidebysig specialname + instance void remove_EventFromFirstType(class [runtime]System.EventHandler`1 'handler') cil managed +{ + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw +} + +.event class [runtime]System.EventHandler`1 EventFromFirstType +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CLIEventAttribute::.ctor() = ( 01 00 00 00 ) + .addon instance void LibraryWithTwoClassesAndTwoEvents/MyClass::add_EventFromFirstType(class [runtime]System.EventHandler`1) + .removeon instance void LibraryWithTwoClassesAndTwoEvents/MyClass::remove_EventFromFirstType(class [runtime]System.EventHandler`1) +} +} + +.class auto ansi serializable nested public MyClass2 + 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: ldnull + IL_0001: throw +} + +.method public hidebysig specialname + instance void add_EventFromSecondType(class [runtime]System.EventHandler`1 'handler') cil managed +{ + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw +} + +.method public hidebysig specialname + instance void remove_EventFromSecondType(class [runtime]System.EventHandler`1 'handler') cil managed +{ + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw +} + +.event class [runtime]System.EventHandler`1 EventFromSecondType +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CLIEventAttribute::.ctor() = ( 01 00 00 00 ) + .addon instance void LibraryWithTwoClassesAndTwoEvents/MyClass2::add_EventFromSecondType(class [runtime]System.EventHandler`1) + .removeon instance void LibraryWithTwoClassesAndTwoEvents/MyClass2::remove_EventFromSecondType(class [runtime]System.EventHandler`1) +""" ] + [] let ``Properties are emitted for CliMutable records`` () = FSharp """