Skip to content

Commit a90f6d1

Browse files
authored
Nullness :: Bugfix :: Codegen missing metadata for C# consumers (records,DUs,exceptions) (#18079)
1 parent b204b96 commit a90f6d1

File tree

153 files changed

+3962
-4740
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

153 files changed

+3962
-4740
lines changed

docs/release-notes/.FSharp.Compiler.Service/9.0.200.md

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* Fix failure to use bound values in `when` clauses of `try-with` in `seq` expressions ([PR #17990](https://github.com/dotnet/fsharp/pull/17990))
1515
* Fix locals allocating for the special `copyOfStruct` defensive copy ([PR #18025](https://github.com/dotnet/fsharp/pull/18025))
1616
* Fix lowering of computed array expressions when the expression consists of a simple mapping from a `uint64` or `unativeint` array. [PR #18081](https://github.com/dotnet/fsharp/pull/18081)
17+
* Add missing nullable-metadata for C# consumers of records,exceptions and DU subtypes generated from F# code. [PR #18079](https://github.com/dotnet/fsharp/pull/18079)
1718

1819

1920
### Added

src/Compiler/AbstractIL/il.fs

+14-3
Original file line numberDiff line numberDiff line change
@@ -4208,14 +4208,25 @@ let mkILStorageCtorWithParamNames (preblock: ILInstr list, ty, extraParams, flds
42084208
| Some x -> I_seqpoint x
42094209
| None -> ()
42104210
yield! preblock
4211-
for (n, (_pnm, nm, fieldTy)) in List.indexed flds do
4211+
for (n, (_pnm, nm, fieldTy,_attrs)) in List.indexed flds do
42124212
mkLdarg0
42134213
mkLdarg (uint16 (n + 1))
42144214
mkNormalStfld (mkILFieldSpecInTy (ty, nm, fieldTy))
42154215
]
42164216

42174217
let body = mkMethodBody (false, [], 2, nonBranchingInstrsToCode code, tag, imports)
4218-
mkILCtor (access, (flds |> List.map (fun (pnm, _, ty) -> mkILParamNamed (pnm, ty))) @ extraParams, body)
4218+
let fieldParams =
4219+
[
4220+
for (pnm,_,ty,attrs) in flds do
4221+
let ilParam = mkILParamNamed (pnm, ty)
4222+
let ilParam =
4223+
match attrs with
4224+
| [] -> ilParam
4225+
| attrs -> {ilParam with CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs attrs ) }
4226+
yield ilParam
4227+
]
4228+
4229+
mkILCtor (access, fieldParams @ extraParams , body)
42194230

42204231
let mkILSimpleStorageCtorWithParamNames (baseTySpec, ty, extraParams, flds, access, tag, imports) =
42214232
let preblock =
@@ -4226,7 +4237,7 @@ let mkILSimpleStorageCtorWithParamNames (baseTySpec, ty, extraParams, flds, acce
42264237
mkILStorageCtorWithParamNames (preblock, ty, extraParams, flds, access, tag, imports)
42274238

42284239
let addParamNames flds =
4229-
flds |> List.map (fun (nm, ty) -> (nm, nm, ty))
4240+
flds |> List.map (fun (nm, ty, attrs) -> (nm, nm, ty, attrs))
42304241

42314242
let mkILSimpleStorageCtor (baseTySpec, ty, extraParams, flds, access, tag, imports) =
42324243
mkILSimpleStorageCtorWithParamNames (baseTySpec, ty, extraParams, addParamNames flds, access, tag, imports)

src/Compiler/AbstractIL/il.fsi

+8-3
Original file line numberDiff line numberDiff line change
@@ -2217,14 +2217,19 @@ val internal prependInstrsToClassCtor:
22172217

22182218
/// Derived functions for making some simple constructors
22192219
val internal mkILStorageCtor:
2220-
ILInstr list * ILType * (string * ILType) list * ILMemberAccess * ILDebugPoint option * ILDebugImports option ->
2220+
ILInstr list *
2221+
ILType *
2222+
(string * ILType * ILAttribute list) list *
2223+
ILMemberAccess *
2224+
ILDebugPoint option *
2225+
ILDebugImports option ->
22212226
ILMethodDef
22222227

22232228
val internal mkILSimpleStorageCtor:
22242229
ILTypeSpec option *
22252230
ILType *
22262231
ILParameter list *
2227-
(string * ILType) list *
2232+
(string * ILType * ILAttribute list) list *
22282233
ILMemberAccess *
22292234
ILDebugPoint option *
22302235
ILDebugImports option ->
@@ -2234,7 +2239,7 @@ val internal mkILSimpleStorageCtorWithParamNames:
22342239
ILTypeSpec option *
22352240
ILType *
22362241
ILParameter list *
2237-
(string * string * ILType) list *
2242+
(string * string * ILType * ILAttribute list) list *
22382243
ILMemberAccess *
22392244
ILDebugPoint option *
22402245
ILDebugImports option ->

src/Compiler/CodeGen/EraseClosures.fs

+2-2
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ let rec convIlxClosureDef cenv encl (td: ILTypeDef) clo =
560560
mkILStorageCtor (
561561
[ mkLdarg0; mkNormalCall (mkILCtorMethSpecForTy (cenv.mkILTyFuncTy, [])) ],
562562
nowTy,
563-
mkILCloFldSpecs cenv nowFields,
563+
mkILCloFldSpecs cenv nowFields |> List.map (fun (name, t) -> (name, t, [])),
564564
ILMemberAccess.Assembly,
565565
None,
566566
None
@@ -695,7 +695,7 @@ let rec convIlxClosureDef cenv encl (td: ILTypeDef) clo =
695695
mkILStorageCtor (
696696
[ mkLdarg0; mkNormalCall (mkILCtorMethSpecForTy (nowEnvParentClass, [])) ],
697697
nowTy,
698-
mkILCloFldSpecs cenv nowFields,
698+
mkILCloFldSpecs cenv nowFields |> List.map (fun (name, t) -> (name, t, [])),
699699
ILMemberAccess.Assembly,
700700
None,
701701
cloImports

src/Compiler/CodeGen/EraseUnions.fs

+50-28
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,18 @@ let mkUnionCaseFieldId (fdef: IlxUnionCaseField) =
214214
// Use the lower case name of a field or constructor as the field/parameter name if it differs from the uppercase name
215215
fdef.LowerName, fdef.Type
216216

217+
let inline getFieldsNullability (g: TcGlobals) (ilf: ILFieldDef) =
218+
if g.checkNullness then
219+
ilf.CustomAttrs.AsArray()
220+
|> Array.tryFind (IsILAttrib g.attrib_NullableAttribute)
221+
else
222+
None
223+
224+
let mkUnionCaseFieldIdAndAttrs g fdef =
225+
let nm, t = mkUnionCaseFieldId fdef
226+
let attrs = getFieldsNullability g fdef.ILField
227+
nm, t, attrs |> Option.toList
228+
217229
let refToFieldInTy ty (nm, fldTy) = mkILFieldSpecInTy (ty, nm, fldTy)
218230

219231
let formalTypeArgs (baseTy: ILType) =
@@ -711,14 +723,9 @@ let mkMethodsAndPropertiesForFields
711723
let ilReturn = mkILReturn field.Type
712724

713725
let ilReturn =
714-
if TryFindILAttribute g.attrib_NullableAttribute field.ILField.CustomAttrs then
715-
let attrs =
716-
field.ILField.CustomAttrs.AsArray()
717-
|> Array.filter (IsILAttrib g.attrib_NullableAttribute)
718-
719-
ilReturn.WithCustomAttrs(mkILCustomAttrsFromArray attrs)
720-
else
721-
ilReturn
726+
match getFieldsNullability g field.ILField with
727+
| None -> ilReturn
728+
| Some a -> ilReturn.WithCustomAttrs(mkILCustomAttrsFromArray [| a |])
722729

723730
yield
724731
mkILNonGenericInstanceMethod (
@@ -808,22 +815,19 @@ let convAlternativeDef
808815
|> Array.map (fun fd ->
809816
let plainParam = mkILParamNamed (fd.LowerName, fd.Type)
810817

811-
if TryFindILAttribute g.attrib_NullableAttribute fd.ILField.CustomAttrs then
812-
let attrs =
813-
fd.ILField.CustomAttrs.AsArray()
814-
|> Array.filter (IsILAttrib g.attrib_NullableAttribute)
815-
818+
match getFieldsNullability g fd.ILField with
819+
| None -> plainParam
820+
| Some a ->
816821
{ plainParam with
817-
CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrsFromArray attrs)
818-
}
819-
else
820-
plainParam)
822+
CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrsFromArray [| a |])
823+
})
824+
821825
|> Array.toList,
822826
mkILReturn baseTy,
823827
mkMethodBody (true, locals, fields.Length + locals.Length, nonBranchingInstrsToCode ilInstrs, attr, imports)
824828
)
825-
|> addMethodGeneratedAttrs
826829
|> addAltAttribs
830+
|> addMethodGeneratedAttrs
827831

828832
mdef
829833

@@ -984,8 +988,8 @@ let convAlternativeDef
984988
imports
985989
)
986990
)
987-
|> addMethodGeneratedAttrs
988991
|> addAltAttribs
992+
|> addMethodGeneratedAttrs
989993

990994
let nullaryProp =
991995

@@ -1158,14 +1162,19 @@ let convAlternativeDef
11581162
let basicFields =
11591163
fields
11601164
|> Array.map (fun field ->
1161-
let fldName, fldTy = mkUnionCaseFieldId field
1165+
let fldName, fldTy, attrs = mkUnionCaseFieldIdAndAttrs g field
1166+
let fdef = mkILInstanceField (fldName, fldTy, None, ILMemberAccess.Assembly)
11621167

11631168
let fdef =
1164-
mkILInstanceField (fldName, fldTy, None, ILMemberAccess.Assembly)
1169+
match attrs with
1170+
| [] -> fdef
1171+
| attrs -> fdef.With(customAttrs = mkILCustomAttrs attrs)
1172+
11651173
|> addFieldNeverAttrs
11661174
|> addFieldGeneratedAttrs
11671175

11681176
fdef.WithInitOnly(isTotallyImmutable))
1177+
11691178
|> Array.toList
11701179

11711180
let basicProps, basicMethods =
@@ -1198,7 +1207,11 @@ let convAlternativeDef
11981207
cud.UnionCasesAccessibility)
11991208

12001209
let basicCtorFields =
1201-
basicFields |> List.map (fun fdef -> fdef.Name, fdef.FieldType)
1210+
basicFields
1211+
|> List.map (fun fdef ->
1212+
let existingAttrs = fdef.CustomAttrs.AsArray()
1213+
let nullableAttr = getFieldsNullability g fdef |> Option.toList
1214+
fdef.Name, fdef.FieldType, nullableAttr)
12021215

12031216
let basicCtorMeth =
12041217
(mkILStorageCtor (basicCtorInstrs, altTy, basicCtorFields, basicCtorAccess, attr, imports))
@@ -1295,7 +1308,7 @@ let mkClassUnionDef
12951308
| SingleCase
12961309
| RuntimeTypes
12971310
| TailOrNull -> []
1298-
| IntegerTag -> [ mkTagFieldId g.ilg cuspec ]
1311+
| IntegerTag -> [ let n, t = mkTagFieldId g.ilg cuspec in n, t, [] ]
12991312

13001313
let isStruct = td.IsStruct
13011314

@@ -1320,8 +1333,6 @@ let mkClassUnionDef
13201333
repr.RepresentAlternativeAsFreshInstancesOfRootClass(info, alt)
13211334
|| repr.RepresentAlternativeAsStructValue info
13221335
then
1323-
// TODO
1324-
let fields = alt.FieldDefs |> Array.map mkUnionCaseFieldId |> Array.toList
13251336

13261337
let baseInit =
13271338
if isStruct then
@@ -1337,6 +1348,9 @@ let mkClassUnionDef
13371348
if isStruct && not (cidx = minNullaryIdx) then
13381349
[]
13391350
else
1351+
let fields =
1352+
alt.FieldDefs |> Array.map (mkUnionCaseFieldIdAndAttrs g) |> Array.toList
1353+
13401354
[
13411355
(mkILSimpleStorageCtor (
13421356
baseInit,
@@ -1406,7 +1420,10 @@ let mkClassUnionDef
14061420
fieldDefs
14071421
|> Array.filter (fun f -> fieldsEmitted.Add(struct (f.LowerName, f.Type)))
14081422

1409-
let fields = fieldsToBeAddedIntoType |> Array.map mkUnionCaseFieldId |> Array.toList
1423+
let fields =
1424+
fieldsToBeAddedIntoType
1425+
|> Array.map (mkUnionCaseFieldIdAndAttrs g)
1426+
|> Array.toList
14101427

14111428
let props, meths =
14121429
mkMethodsAndPropertiesForFields
@@ -1426,9 +1443,14 @@ let mkClassUnionDef
14261443

14271444
let selfAndTagFields =
14281445
[
1429-
for fldName, fldTy in (selfFields @ tagFieldsInObject) do
1446+
for fldName, fldTy, attrs in (selfFields @ tagFieldsInObject) do
14301447
let fdef =
1431-
mkILInstanceField (fldName, fldTy, None, ILMemberAccess.Assembly)
1448+
let fdef = mkILInstanceField (fldName, fldTy, None, ILMemberAccess.Assembly)
1449+
1450+
match attrs with
1451+
| [] -> fdef
1452+
| attrs -> fdef.With(customAttrs = mkILCustomAttrs attrs)
1453+
14321454
|> addFieldNeverAttrs
14331455
|> addFieldGeneratedAttrs
14341456

0 commit comments

Comments
 (0)