Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Nullness interop - import of C#-emitted metadata #16423

Merged
merged 49 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
f058226
failing test
T-Gro Dec 5, 2023
c24a746
todo for IL import
T-Gro Dec 5, 2023
37a2752
explanation added
T-Gro Dec 6, 2023
baca949
il meta parsing
T-Gro Dec 7, 2023
feeb098
flags evaluation
T-Gro Dec 7, 2023
cfa416f
you shall passs
T-Gro Dec 7, 2023
ac5ff27
evaluateFirstOrderNullnessAndAdvance
T-Gro Dec 7, 2023
62aa534
import il type with nullness
T-Gro Dec 11, 2023
06623df
type import
T-Gro Dec 12, 2023
2aa9722
IL nullness import
T-Gro Dec 12, 2023
469e10b
test rename
T-Gro Dec 12, 2023
db1bfac
fantomas
T-Gro Dec 12, 2023
b4551a7
Merge branch 'feature/nullness' into nullness-interop-import
T-Gro Dec 12, 2023
1e94203
Merge branch 'feature/nullness' into nullness-interop-import
T-Gro Dec 12, 2023
94e02aa
get stack trace on error
T-Gro Dec 12, 2023
4d2f36f
split ilmethod's type
T-Gro Dec 13, 2023
e186b6a
fix crashes for Csharp style extensions
T-Gro Dec 13, 2023
d084a93
solve coexistance of nullness and Is* properties of DUs
T-Gro Dec 14, 2023
8381659
updating tests
T-Gro Dec 14, 2023
eabfeaf
clean tests
T-Gro Dec 14, 2023
334b118
fantomas
T-Gro Dec 14, 2023
f16054e
fantomas one more time
T-Gro Dec 14, 2023
4ebb2cb
importing nullness for generic typars
T-Gro Dec 14, 2023
0d6d764
print failing ivals, let's see
T-Gro Dec 15, 2023
4b9b4b2
write even more!
T-Gro Dec 15, 2023
14cf8fa
isolated failing test - combo of module rec, signature file, IVT
T-Gro Dec 19, 2023
01d0671
another attempt
T-Gro Dec 20, 2023
e0e7c28
format
T-Gro Dec 20, 2023
92267fc
test
T-Gro Jan 3, 2024
3d2ed8b
hide tests
T-Gro Jan 4, 2024
affe0c8
Remove 'specialname' for DU case tester
T-Gro Jan 4, 2024
bba7521
format
T-Gro Jan 4, 2024
0055376
warning as error
T-Gro Jan 4, 2024
939f6da
update baseline netcore
T-Gro Jan 4, 2024
c781a6a
nullable errors not in desktop framework
T-Gro Jan 5, 2024
384cc32
surface area, trimming
T-Gro Jan 5, 2024
a0f19f8
surface area
T-Gro Jan 5, 2024
3567765
cosmetic cleanup & annotations
T-Gro Jan 5, 2024
cc37881
Rename to ILMethParentTypeInfo
T-Gro Jan 10, 2024
3c58861
making vMapFold tail recursive
T-Gro Jan 10, 2024
ab07699
physical nullnessEquiv
T-Gro Jan 10, 2024
b5522c8
format
T-Gro Jan 10, 2024
0e4a3e2
Commenting SkipNullness usages
T-Gro Jan 15, 2024
04ec256
Nullness work - activity module
T-Gro Jan 15, 2024
cd4632f
Remove strict generic 'T:null' import
T-Gro Jan 16, 2024
45a6bdf
Null|NonNull pattern also for regular compilation
T-Gro Jan 16, 2024
abe07b2
Backported Null|NonNull active pattern
T-Gro Jan 16, 2024
7a4dbf6
one more time
T-Gro Jan 16, 2024
1141fe4
revert
T-Gro Jan 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion src/Compiler/AbstractIL/il.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,13 @@ type ILAttributes =

/// Represents the efficiency-oriented storage of ILAttributes in another item.
[<NoEquality; NoComparison>]
type ILAttributesStored
type ILAttributesStored =
/// Computed by ilread.fs based on metadata index
| Reader of (int32 -> ILAttribute[])
/// Already computed
| Given of ILAttributes

member GetCustomAttrs: int32 -> ILAttributes

/// Method parameters and return values.
[<RequireQualifiedAccess; NoEquality; NoComparison>]
Expand Down Expand Up @@ -1069,6 +1075,8 @@ type ILMethodDef =
member IsEntryPoint: bool
member GenericParams: ILGenericParameterDefs
member CustomAttrs: ILAttributes
member MetadataIndex: int32
member CustomAttrsStored: ILAttributesStored
member ParameterTypes: ILTypes
member IsIL: bool
member Code: ILCode option
Expand Down Expand Up @@ -1242,6 +1250,10 @@ type ILFieldDef =

member CustomAttrs: ILAttributes

member MetadataIndex: int32

member CustomAttrsStored: ILAttributesStored

member IsStatic: bool

member IsSpecialName: bool
Expand Down Expand Up @@ -1325,6 +1337,8 @@ type ILEventDef =
member FireMethod: ILMethodRef option
member OtherMethods: ILMethodRef list
member CustomAttrs: ILAttributes
member MetadataIndex: int32
member CustomAttrsStored: ILAttributesStored
member IsSpecialName: bool
member IsRTSpecialName: bool

Expand Down Expand Up @@ -1387,6 +1401,8 @@ type ILPropertyDef =
member Init: ILFieldInit option
member Args: ILTypes
member CustomAttrs: ILAttributes
member MetadataIndex: int32
member CustomAttrsStored: ILAttributesStored
member IsSpecialName: bool
member IsRTSpecialName: bool

Expand Down Expand Up @@ -1538,6 +1554,8 @@ type ILTypeDef =
member Events: ILEventDefs
member Properties: ILPropertyDefs
member CustomAttrs: ILAttributes
member MetadataIndex: int32
member CustomAttrsStored: ILAttributesStored
member IsClass: bool
member IsStruct: bool
member IsInterface: bool
Expand Down
4 changes: 2 additions & 2 deletions src/Compiler/Checking/AccessibilityLogic.fs
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,8 @@ let IsILEventInfoAccessible g amap m ad einfo =

let private IsILMethInfoAccessible g amap m adType ad ilminfo =
match ilminfo with
| ILMethInfo (_, ty, None, mdef, _) -> IsILTypeAndMemberAccessible g amap m adType ad (ILTypeInfo.FromType g ty) mdef.Access
| ILMethInfo (_, _, Some declaringTyconRef, mdef, _) -> IsILMemberAccessible g amap m declaringTyconRef ad mdef.Access
| ILMethInfo (_, IlType ty, mdef, _) -> IsILTypeAndMemberAccessible g amap m adType ad ty mdef.Access
| ILMethInfo (_, CSharpStyleExtension(declaring=declaringTyconRef), mdef, _) -> IsILMemberAccessible g amap m declaringTyconRef ad mdef.Access

let GetILAccessOfILPropInfo (ILPropInfo(tinfo, pdef)) =
let tdef = tinfo.RawMetadata
Expand Down
9 changes: 6 additions & 3 deletions src/Compiler/Checking/AttributeChecking.fs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ type AttribInfo =
match x with
| FSAttribInfo(_g, Attrib(tcref, _, _, _, _, _, _)) -> tcref
| ILAttribInfo (g, amap, scoref, a, m) ->
let ty = RescopeAndImportILType scoref amap m [] a.Method.DeclaringType
// We are skipping nullness check here because this reference is an attribute usage, nullness does not apply.
let ty = RescopeAndImportILTypeSkipNullness scoref amap m [] a.Method.DeclaringType
tcrefOfAppTy g ty

member x.ConstructorArguments =
Expand All @@ -104,7 +105,8 @@ type AttribInfo =
| ILAttribInfo (_g, amap, scoref, cattr, m) ->
let parms, _args = decodeILAttribData cattr
[ for argTy, arg in Seq.zip cattr.Method.FormalArgTypes parms ->
let ty = RescopeAndImportILType scoref amap m [] argTy
// We are skipping nullness check here because this reference is an attribute usage, nullness does not apply.
let ty = RescopeAndImportILTypeSkipNullness scoref amap m [] argTy
let obj = evalILAttribElem arg
ty, obj ]

Expand All @@ -119,7 +121,8 @@ type AttribInfo =
| ILAttribInfo (_g, amap, scoref, cattr, m) ->
let _parms, namedArgs = decodeILAttribData cattr
[ for nm, argTy, isProp, arg in namedArgs ->
let ty = RescopeAndImportILType scoref amap m [] argTy
// We are skipping nullness check here because this reference is an attribute usage, nullness does not apply.
let ty = RescopeAndImportILTypeSkipNullness scoref amap m [] argTy
let obj = evalILAttribElem arg
let isField = not isProp
ty, nm, isField, obj ]
Expand Down
18 changes: 10 additions & 8 deletions src/Compiler/Checking/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4708,14 +4708,16 @@ module TcDeclarations =
MutRecBindingChecking.TcMutRecDefns_UpdateModuleContents mutRecNSInfo mutRecDefnsAfterVals

// Generate the union augmentation values for all tycons.
(envMutRec, mutRecDefnsAfterCore) ||> MutRecShapes.iterTyconsWithEnv (fun envForDecls ((tyconCore, _, _), tyconOpt, _, _, _) ->
let (MutRecDefnsPhase1DataForTycon (isAtOriginalTyconDefn=isAtOriginalTyconDefn)) = tyconCore
match tyconOpt with
| Some tycon when isAtOriginalTyconDefn ->
if tycon.IsUnionTycon && AddAugmentationDeclarations.ShouldAugmentUnion cenv.g tycon then
let vspecs = AddAugmentationDeclarations.AddUnionAugmentationValues cenv envForDecls tycon
ignore vspecs
| _ -> ())
// TODO nullness :: this is the handling of DU .Is* properties WITHIN signature files.
// Watch https://github.com/fsharp/fslang-design/discussions
//(envMutRec, mutRecDefnsAfterCore) ||> MutRecShapes.iterTyconsWithEnv (fun envForDecls ((tyconCore, _, _), tyconOpt, _, _, _) ->
// let (MutRecDefnsPhase1DataForTycon (isAtOriginalTyconDefn=isAtOriginalTyconDefn)) = tyconCore
// match tyconOpt with
// | Some tycon when isAtOriginalTyconDefn ->
// if tycon.IsUnionTycon && AddAugmentationDeclarations.ShouldAugmentUnion cenv.g tycon then
// let vspecs = AddAugmentationDeclarations.AddUnionAugmentationValues cenv envForDecls tycon
// ignore vspecs
// | _ -> ())

envMutRec

Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Checking/InfoReader.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1142,7 +1142,7 @@ let GetXmlDocSigOfMethInfo (infoReader: InfoReader) m (minfo: MethInfo) =
match TryFindMetadataInfoOfExternalEntityRef infoReader m ilminfo.DeclaringTyconRef with
| None -> None
| Some (ccuFileName, formalTypars, formalTypeInfo) ->
let filminfo = ILMethInfo(g, formalTypeInfo.ToType, None, ilminfo.RawMetadata, fmtps)
let filminfo = ILMethInfo(g, IlType formalTypeInfo, ilminfo.RawMetadata, fmtps)
let args =
if ilminfo.IsILExtensionMethod then
filminfo.GetRawArgTypes(amap, m, minfo.FormalMethodInst)
Expand Down
10 changes: 5 additions & 5 deletions src/Compiler/Checking/NicePrint.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1646,14 +1646,14 @@ module InfoMemberPrinting =

// Prettify an ILMethInfo
let prettifyILMethInfo (amap: Import.ImportMap) m (minfo: MethInfo) typarInst ilMethInfo =
let (ILMethInfo(_, apparentTy, dty, mdef, _)) = ilMethInfo
let (prettyTyparInst, prettyTys), _ = PrettyTypes.PrettifyInstAndTypes amap.g (typarInst, (apparentTy :: minfo.FormalMethodInst))
let (ILMethInfo(_, methodsType, mdef, _)) = ilMethInfo
let (prettyTyparInst, prettyTys), _ = PrettyTypes.PrettifyInstAndTypes amap.g (typarInst, (methodsType.ToType :: minfo.FormalMethodInst))
match prettyTys with
| prettyApparentTy :: prettyFormalMethInst ->
let prettyMethInfo =
match dty with
| None -> MethInfo.CreateILMeth (amap, m, prettyApparentTy, mdef)
| Some declaringTyconRef -> MethInfo.CreateILExtensionMeth(amap, m, prettyApparentTy, declaringTyconRef, minfo.ExtensionMemberPriorityOption, mdef)
match methodsType with
| IlType _ -> MethInfo.CreateILMeth (amap, m, prettyApparentTy, mdef)
| CSharpStyleExtension(declaring=declaringTyconRef) -> MethInfo.CreateILExtensionMeth(amap, m, prettyApparentTy, declaringTyconRef, minfo.ExtensionMemberPriorityOption, mdef)
prettyTyparInst, prettyMethInfo, prettyFormalMethInst
| _ -> failwith "prettifyILMethInfo - prettyTys empty"

Expand Down
31 changes: 19 additions & 12 deletions src/Compiler/Checking/TypeHierarchy.fs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ let GetSuperTypeOfType g amap m ty =
let tinst = argsOfAppTy g ty
match tdef.Extends with
| None -> None
| Some ilTy -> Some (RescopeAndImportILType scoref amap m tinst ilTy)
// 'inherit' cannot refer to a nullable type
| Some ilTy -> Some (RescopeAndImportILTypeSkipNullness scoref amap m tinst ilTy)

| FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata ->
if isFSharpObjModelTy g ty || isFSharpExceptionTy g ty then
Expand Down Expand Up @@ -115,7 +116,8 @@ let GetImmediateInterfacesOfMetadataType g amap m skipUnref ty (tcref: TyconRef)
// assume those are present.
for intfTy in tdef.Implements do
if skipUnref = SkipUnrefInterfaces.No || CanRescopeAndImportILType scoref amap m intfTy then
RescopeAndImportILType scoref amap m tinst intfTy
// Implementing an interface cannot refer to a nullable type
RescopeAndImportILTypeSkipNullness scoref amap m tinst intfTy
| FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata ->
for intfTy in tcref.ImmediateInterfaceTypesOfFSharpTycon do
instType (mkInstForAppTy g ty) intfTy ]
Expand Down Expand Up @@ -356,33 +358,38 @@ let ExistsHeadTypeInEntireHierarchy g amap m typeToSearchFrom tcrefToLookFor =
ExistsInEntireHierarchyOfType (HasHeadType g tcrefToLookFor) g amap m AllowMultiIntfInstantiations.Yes typeToSearchFrom

/// Read an Abstract IL type from metadata and convert to an F# type.
let ImportILTypeFromMetadata amap m scoref tinst minst ilTy =
RescopeAndImportILType scoref amap m (tinst@minst) ilTy
let ImportILTypeFromMetadata amap m scoref tinst minst nullnessSource ilTy =
RescopeAndImportILType scoref amap m (tinst@minst) nullnessSource ilTy

/// Read an Abstract IL type from metadata and convert to an F# type, ignoring nullness checking.
let ImportILTypeFromMetadataSkipNullness amap m scoref tinst minst ilTy =
RescopeAndImportILTypeSkipNullness scoref amap m (tinst@minst) ilTy

/// Read an Abstract IL type from metadata, including any attributes that may affect the type itself, and convert to an F# type.
let ImportILTypeFromMetadataWithAttributes amap m scoref tinst minst ilTy getCattrs =
let ty = RescopeAndImportILType scoref amap m (tinst@minst) ilTy
let ImportILTypeFromMetadataWithAttributes amap m scoref tinst minst nullnessSource ilTy =
let ty = RescopeAndImportILType scoref amap m (tinst@minst) nullnessSource ilTy

// If the type is a byref and one of attributes from a return or parameter has
// - a `IsReadOnlyAttribute` - it's an inref
// - a `RequiresLocationAttribute` (in which case it's a `ref readonly`) which we treat as inref,
// latter is an ad-hoc fix for https://github.com/dotnet/runtime/issues/94317.
if isByrefTy amap.g ty
&& (TryFindILAttribute amap.g.attrib_IsReadOnlyAttribute (getCattrs ())
|| TryFindILAttribute amap.g.attrib_RequiresLocationAttribute (getCattrs ())) then
&& (TryFindILAttribute amap.g.attrib_IsReadOnlyAttribute (nullnessSource.DirectAttributes.Read())
|| TryFindILAttribute amap.g.attrib_RequiresLocationAttribute (nullnessSource.DirectAttributes.Read())) then
mkInByrefTy amap.g (destByrefTy amap.g ty)
else
ty

/// Get the parameter type of an IL method.
let ImportParameterTypeFromMetadata amap m ilTy getCattrs scoref tinst mist =
ImportILTypeFromMetadataWithAttributes amap m scoref tinst mist ilTy getCattrs
let ImportParameterTypeFromMetadata amap m nullnessSource ilTy scoref tinst mist =
ImportILTypeFromMetadataWithAttributes amap m scoref tinst mist nullnessSource ilTy

/// Get the return type of an IL method, taking into account instantiations for type, return attributes and method generic parameters, and
/// translating 'void' to 'None'.
let ImportReturnTypeFromMetadata amap m ilTy getCattrs scoref tinst minst =
let ImportReturnTypeFromMetadata amap m nullnessSource ilTy scoref tinst minst =
match ilTy with
| ILType.Void -> None
| retTy -> Some(ImportILTypeFromMetadataWithAttributes amap m scoref tinst minst retTy getCattrs)
| retTy -> Some(ImportILTypeFromMetadataWithAttributes amap m scoref tinst minst nullnessSource retTy )


/// Copy constraints. If the constraint comes from a type parameter associated
Expand Down
17 changes: 14 additions & 3 deletions src/Compiler/Checking/TypeHierarchy.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,17 @@ val ExistsHeadTypeInEntireHierarchy:

/// Read an Abstract IL type from metadata and convert to an F# type.
val ImportILTypeFromMetadata:
amap: ImportMap ->
m: range ->
scoref: ILScopeRef ->
tinst: TType list ->
minst: TType list ->
nullnessSource: Nullness.NullableAttributesSource ->
ilTy: ILType ->
TType

/// Read an Abstract IL type from metadata and convert to an F# type, ignoring nullness checking.
val ImportILTypeFromMetadataSkipNullness:
amap: ImportMap -> m: range -> scoref: ILScopeRef -> tinst: TType list -> minst: TType list -> ilTy: ILType -> TType

/// Read an Abstract IL type from metadata, including any attributes that may affect the type itself, and convert to an F# type.
Expand All @@ -126,16 +137,16 @@ val ImportILTypeFromMetadataWithAttributes:
scoref: ILScopeRef ->
tinst: TType list ->
minst: TType list ->
nullnessSource: Nullness.NullableAttributesSource ->
ilTy: ILType ->
getCattrs: (unit -> ILAttributes) ->
TType

/// Get the parameter type of an IL method.
val ImportParameterTypeFromMetadata:
amap: ImportMap ->
m: range ->
nullnessSource: Nullness.NullableAttributesSource ->
ilTy: ILType ->
getCattrs: (unit -> ILAttributes) ->
scoref: ILScopeRef ->
tinst: TType list ->
mist: TType list ->
Expand All @@ -146,8 +157,8 @@ val ImportParameterTypeFromMetadata:
val ImportReturnTypeFromMetadata:
amap: ImportMap ->
m: range ->
nullnessSource: Nullness.NullableAttributesSource ->
ilTy: ILType ->
getCattrs: (unit -> ILAttributes) ->
scoref: ILScopeRef ->
tinst: TType list ->
minst: TType list ->
Expand Down
Loading
Loading