Plumb generic metadata through (#107)

This commit is contained in:
Patrick Stevens
2025-08-23 15:18:05 +01:00
committed by GitHub
parent 3bdfeaf8a1
commit 92f22cff42
15 changed files with 228 additions and 220 deletions

View File

@@ -52,74 +52,6 @@ module Parameter =
result.ToImmutable ()
type GenericVariance =
| Covariant
| Contravariant
type GenericConstraint =
| Reference
| NonNullableValue
/// <summary>
/// Represents a generic type or method parameter definition.
/// Corresponds to GenericParameter in System.Reflection.Metadata.
/// </summary>
type GenericParameter =
{
/// <summary>The name of the generic parameter (e.g., 'T', 'TKey', etc.).</summary>
Name : string
/// <summary>
/// The zero-based index of the generic parameter in the generic parameter list.
/// For example, in Dictionary&lt;TKey, TValue&rt;, TKey has index 0 and TValue has index 1.
/// </summary>
SequenceNumber : int
Variance : GenericVariance option
Constraint : GenericConstraint option
RequiresParameterlessConstructor : bool
}
[<RequireQualifiedAccess>]
module GenericParameter =
let readAll
(metadata : MetadataReader)
(param : GenericParameterHandleCollection)
: GenericParameter ImmutableArray
=
param
|> Seq.map (fun param ->
let param = metadata.GetGenericParameter param
let requiresParamlessCons =
param.Attributes.HasFlag GenericParameterAttributes.DefaultConstructorConstraint
let constr =
if param.Attributes.HasFlag GenericParameterAttributes.NotNullableValueTypeConstraint then
Some GenericConstraint.NonNullableValue
elif param.Attributes.HasFlag GenericParameterAttributes.ReferenceTypeConstraint then
Some GenericConstraint.Reference
else
None
let variance =
if param.Attributes.HasFlag GenericParameterAttributes.Contravariant then
Some GenericVariance.Contravariant
elif param.Attributes.HasFlag GenericParameterAttributes.Covariant then
Some GenericVariance.Covariant
else
None
{
Name = metadata.GetString param.Name
SequenceNumber = param.Index
Variance = variance
Constraint = constr
RequiresParameterlessConstructor = requiresParamlessCons
}
)
|> ImmutableArray.CreateRange
type ExceptionOffset =
{
TryLength : int
@@ -202,8 +134,7 @@ module MethodInstructions =
/// Represents detailed information about a method in a .NET assembly.
/// This is a strongly-typed representation of MethodDefinition from System.Reflection.Metadata.
/// </summary>
type MethodInfo<'typeGenerics, 'methodGenerics, 'methodVars
when 'typeGenerics :> IComparable<'typeGenerics> and 'typeGenerics : comparison> =
type MethodInfo<'typeGenerics, 'methodGenerics, 'methodVars> =
{
/// <summary>
/// The type that declares this method, along with its assembly information.
@@ -301,14 +232,13 @@ module MethodInfo =
| con -> failwith $"TODO: {con}"
)
let mapTypeGenerics<'a, 'b, 'methodGen, 'vars
when 'a :> IComparable<'a> and 'a : comparison and 'b : comparison and 'b :> IComparable<'b>>
(f : int -> 'a -> 'b)
let mapTypeGenerics<'a, 'b, 'methodGen, 'vars>
(f : 'a -> 'b)
(m : MethodInfo<'a, 'methodGen, 'vars>)
: MethodInfo<'b, 'methodGen, 'vars>
=
{
DeclaringType = m.DeclaringType |> ConcreteType.mapGeneric f
DeclaringType = m.DeclaringType |> ConcreteType.mapGeneric (fun _ -> f)
Handle = m.Handle
Name = m.Name
Instructions = m.Instructions
@@ -322,18 +252,20 @@ module MethodInfo =
IsStatic = m.IsStatic
}
let mapMethodGenerics<'a, 'b, 'vars, 'typeGen when 'typeGen :> IComparable<'typeGen> and 'typeGen : comparison>
let mapMethodGenerics<'a, 'b, 'vars, 'typeGen>
(f : int -> 'a -> 'b)
(m : MethodInfo<'typeGen, 'a, 'vars>)
: MethodInfo<'typeGen, 'b, 'vars>
=
let generics = m.Generics |> Seq.mapi f |> ImmutableArray.CreateRange
{
DeclaringType = m.DeclaringType
Handle = m.Handle
Name = m.Name
Instructions = m.Instructions
Parameters = m.Parameters
Generics = m.Generics |> Seq.mapi f |> ImmutableArray.CreateRange
Generics = generics
Signature = m.Signature
RawSignature = m.RawSignature
CustomAttributes = m.CustomAttributes
@@ -710,7 +642,7 @@ module MethodInfo =
(peReader : PEReader)
(metadataReader : MetadataReader)
(methodHandle : MethodDefinitionHandle)
: MethodInfo<FakeUnit, GenericParameter, TypeDefn> option
: MethodInfo<GenericParamFromMetadata, GenericParamFromMetadata, TypeDefn> option
=
let logger = loggerFactory.CreateLogger "MethodInfo"
let assemblyName = metadataReader.GetAssemblyDefinition().GetAssemblyName ()
@@ -751,7 +683,8 @@ module MethodInfo =
let declaringTypeName = metadataReader.GetString declaringDefn.Name
let declaringTypeGenericParams =
metadataReader.GetTypeDefinition(declaringType).GetGenericParameters().Count
metadataReader.GetTypeDefinition(declaringType).GetGenericParameters ()
|> GenericParameter.readAll metadataReader
let attrs =
let result = ImmutableArray.CreateBuilder ()
@@ -772,7 +705,7 @@ module MethodInfo =
GenericParameter.readAll metadataReader (methodDef.GetGenericParameters ())
let declaringType =
ConcreteType.make'
ConcreteType.make
assemblyName
declaringType
declaringTypeNamespace