Skip to content

Commit b9dbb1a

Browse files
authored
Merge pull request #14095 from dotnet/merges/release/dev17.4-to-release/dev17.5
Merge release/dev17.4 to release/dev17.5
2 parents 664588e + bacae91 commit b9dbb1a

File tree

2 files changed

+124
-12
lines changed

2 files changed

+124
-12
lines changed

src/Compiler/AbstractIL/ilwrite.fs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,7 @@ let canGenPropertyDef cenv (prop: ILPropertyDef) =
11921192
// If we have GetMethod or SetMethod set (i.e. not None), try and see if we have MethodDefs for them.
11931193
// NOTE: They can be not-None and missing MethodDefs if we skip generating them for reference assembly in the earlier pass.
11941194
// Only generate property if we have at least getter or setter, otherwise, we skip.
1195-
[| prop.GetMethod; prop.SetMethod |]
1195+
[| prop.GetMethod; prop.SetMethod |]
11961196
|> Array.choose id
11971197
|> Array.map (TryGetMethodRefAsMethodDefIdx cenv)
11981198
|> Array.exists (function | Ok _ -> true | _ -> false)
@@ -1304,11 +1304,14 @@ and GenTypeDefPass2 pidx enc cenv (tdef: ILTypeDef) =
13041304
// Now generate or assign index numbers for tables referenced by the maps.
13051305
// Don't yet generate contents of these tables - leave that to pass3, as
13061306
// code may need to embed these entries.
1307-
tdef.Implements |> List.iter (GenImplementsPass2 cenv env tidx)
1308-
props |> List.iter (GenPropertyDefPass2 cenv tidx)
1307+
tdef.Implements |> List.iter (GenImplementsPass2 cenv env tidx)
13091308
events |> List.iter (GenEventDefPass2 cenv tidx)
13101309
tdef.Fields.AsList() |> List.iter (GenFieldDefPass2 tdef cenv tidx)
13111310
tdef.Methods |> Seq.iter (GenMethodDefPass2 tdef cenv tidx)
1311+
// Generation of property definitions for **ref assemblies** is checking existence of generated method definitions.
1312+
// Therefore, due to mutable state within "cenv", order of operations matters.
1313+
// Who could have thought that using shared mutable state can bring unexpected bugs...?
1314+
props |> List.iter (GenPropertyDefPass2 cenv tidx)
13121315
tdef.NestedTypes.AsList() |> GenTypeDefsPass2 tidx (enc@[tdef.Name]) cenv
13131316
with exn ->
13141317
failwith ("Error in pass2 for type "+tdef.Name+", error: " + exn.Message)

tests/fsharp/Compiler/CodeGen/EmittedIL/ReferenceAssemblyTests.fs

Lines changed: 118 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,115 @@ extends [runtime]System.Object
501501
502502
}"""]
503503

504+
[<Test>]
505+
let ``Properties are emitted for CliMutable records`` () =
506+
FSharp """
507+
namespace ReferenceAssembly
508+
type [<CLIMutable;NoComparison;NoEquality>] MyRecord = { MyId: int }"""
509+
|> withOptions ["--refonly"]
510+
|> compile
511+
|> shouldSucceed
512+
|> verifyIL [
513+
referenceAssemblyAttributeExpectedIL
514+
" .property instance int32 MyId()"]
515+
516+
[<Test>]
517+
let ``Properties are emitted even for CliMutable records which are not last in a file`` () =
518+
FSharp """
519+
namespace ReferenceAssembly
520+
type [<CLIMutable;NoComparison;NoEquality>] MyRecord = { MyId: int }
521+
type [<CLIMutable;NoComparison;NoEquality>] MySecondRecord = { MySecondId: string }
522+
"""
523+
|> withOptions ["--refonly"]
524+
|> compile
525+
|> shouldSucceed
526+
|> verifyIL [
527+
referenceAssemblyAttributeExpectedIL
528+
" .property instance int32 MyId()"
529+
" .property instance string MySecondId()"]
530+
531+
[<Test>] // Regression https://github.com/dotnet/fsharp/issues/14088 .
532+
// Generated IL was assigning properties to the last record in file instead of where they are supposed to be
533+
let ``Properties are emitted for equal records in the same file`` () =
534+
FSharp """
535+
namespace Net7FSharpSnafu.Library
536+
537+
open System
538+
539+
type [<CLIMutable;NoComparison;NoEquality>] MyRecord =
540+
{ Name: string }
541+
542+
type [<CLIMutable;NoComparison;NoEquality>] MySecondRecord = { Name: string }
543+
"""
544+
|> withOptions ["--refonly"]
545+
|> compile
546+
|> shouldSucceed
547+
|> verifyIL [""" .class public auto ansi serializable sealed Net7FSharpSnafu.Library.MyRecord
548+
extends [runtime]System.Object
549+
{
550+
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CLIMutableAttribute::.ctor() = ( 01 00 00 00 )
551+
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoComparisonAttribute::.ctor() = ( 01 00 00 00 )
552+
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.NoEqualityAttribute::.ctor() = ( 01 00 00 00 )
553+
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 )
554+
.method public hidebysig specialname instance string
555+
get_Name() cil managed
556+
{
557+
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
558+
.custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 )
559+
560+
.maxstack 8
561+
IL_0000: ldnull
562+
IL_0001: throw
563+
}
564+
565+
.method public hidebysig specialname instance void
566+
set_Name(string 'value') cil managed
567+
{
568+
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
569+
.custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 )
570+
571+
.maxstack 8
572+
IL_0000: ldnull
573+
IL_0001: throw
574+
}
575+
576+
.method public specialname rtspecialname
577+
instance void .ctor(string name) cil managed
578+
{
579+
580+
.maxstack 8
581+
IL_0000: ldnull
582+
IL_0001: throw
583+
}
584+
585+
.method public specialname rtspecialname
586+
instance void .ctor() cil managed
587+
{
588+
589+
.maxstack 8
590+
IL_0000: ldnull
591+
IL_0001: throw
592+
}
593+
594+
.method public strict virtual instance string
595+
ToString() cil managed
596+
{
597+
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
598+
599+
.maxstack 8
600+
IL_0000: ldnull
601+
IL_0001: throw
602+
}
603+
604+
.property instance string Name()
605+
{
606+
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags,
607+
int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 )
608+
.set instance void Net7FSharpSnafu.Library.MyRecord::set_Name(string)
609+
.get instance string Net7FSharpSnafu.Library.MyRecord::get_Name()
610+
}
611+
} """]
612+
504613
[<Test>]
505614
let ``Properties, getters, setters are emitted for internal properties`` () =
506615
FSharp """
@@ -558,6 +667,11 @@ type MySecondaryAttribute() =
558667
IL_0001: throw
559668
}
560669
670+
.property instance int32 Prop1()
671+
{
672+
.set instance void ReferenceAssembly/MyAttribute::set_Prop1(int32)
673+
.get instance int32 ReferenceAssembly/MyAttribute::get_Prop1()
674+
}
561675
}
562676
563677
.class auto ansi serializable nested public MySecondaryAttribute
@@ -597,11 +711,6 @@ type MySecondaryAttribute() =
597711
IL_0001: throw
598712
}
599713
600-
.property instance int32 Prop1()
601-
{
602-
.set instance void ReferenceAssembly/MyAttribute::set_Prop1(int32)
603-
.get instance int32 ReferenceAssembly/MyAttribute::get_Prop1()
604-
}
605714
.property instance int32 Prop1()
606715
{
607716
.set instance void ReferenceAssembly/MySecondaryAttribute::set_Prop1(int32)
@@ -805,6 +914,10 @@ type Person(name : string, age : int) =
805914
IL_0001: throw
806915
}
807916
917+
.property instance bool Something()
918+
{
919+
.get instance bool ReferenceAssembly/CustomAttribute::get_Something()
920+
}
808921
}
809922
810923
.class auto ansi serializable nested public Person
@@ -865,10 +978,6 @@ type Person(name : string, age : int) =
865978
IL_0001: throw
866979
}
867980
868-
.property instance bool Something()
869-
{
870-
.get instance bool ReferenceAssembly/CustomAttribute::get_Something()
871-
}
872981
.property instance string Name()
873982
{
874983
.custom instance void ReferenceAssembly/CustomAttribute::.ctor(bool) = ( 01 00 01 00 00 )

0 commit comments

Comments
 (0)