Skip to content

Commit d07377c

Browse files
committed
Fix more issues related to generic method/type validations and reference, add more test and other implementations
1 parent eccf74e commit d07377c

File tree

7 files changed

+352
-68
lines changed

7 files changed

+352
-68
lines changed

src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/GenericTypeParameterBuilderImpl.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,15 @@ public override Type[] GetGenericParameterConstraints() =>
7575
public override string Name => _name;
7676
public override Module Module => _type.Module;
7777
public override Assembly Assembly => _type.Assembly;
78-
public override string? FullName => _name;
78+
public override string? FullName => null;
7979
public override string? Namespace => null;
8080
public override string? AssemblyQualifiedName => null;
8181
public override Type UnderlyingSystemType => this;
8282
public override bool IsGenericTypeDefinition => false;
8383
public override bool IsGenericType => false;
8484
public override bool IsGenericParameter => true;
8585
public override bool IsConstructedGenericType => false;
86-
public override bool ContainsGenericParameters => _type.ContainsGenericParameters;
86+
public override bool ContainsGenericParameters => false;
8787
public override MethodBase? DeclaringMethod => _type.DeclaringMethod;
8888
public override Type? BaseType => _parent;
8989
public override RuntimeTypeHandle TypeHandle => throw new NotSupportedException();

src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -519,14 +519,22 @@ private MethodSpecificationHandle AddMethodSpecification(EntityHandle methodHand
519519
method: methodHandle,
520520
instantiation: _metadataBuilder.GetOrAddBlob(MetadataSignatureHelper.GetMethodSpecificationSignature(genericArgs, this)));
521521

522+
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:RequiresDynamicCode", Justification = "Test")]
523+
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:RequiresUnreferencedCode", Justification = "Test")]
522524
private EntityHandle GetMemberReferenceHandle(MemberInfo memberInfo)
523525
{
524526
if (!_memberReferences.TryGetValue(memberInfo, out var memberHandle))
525527
{
526528
switch (memberInfo)
527529
{
528530
case FieldInfo field:
529-
memberHandle = AddMemberReference(field.Name, GetTypeHandle(memberInfo.DeclaringType!),
531+
Type declaringType = field.DeclaringType!;
532+
if (field.DeclaringType!.IsGenericTypeDefinition)
533+
{
534+
//The type of the field has to be fully instantiated type.
535+
declaringType = declaringType.MakeGenericType(declaringType.GetGenericArguments());
536+
}
537+
memberHandle = AddMemberReference(field.Name, GetTypeHandle(declaringType),
530538
MetadataSignatureHelper.GetFieldSignature(field.FieldType, field.GetRequiredCustomModifiers(), field.GetOptionalCustomModifiers(), this));
531539
break;
532540
case ConstructorInfo ctor:
@@ -791,7 +799,7 @@ internal EntityHandle GetMemberHandle(MemberInfo member)
791799
return ctor._methodBuilder._handle;
792800
}
793801

794-
if (member is FieldBuilderImpl fb && Equals(fb.Module))
802+
if (member is FieldBuilderImpl fb && Equals(fb.Module) && !fb.DeclaringType!.IsGenericTypeDefinition)
795803
{
796804
return fb._handle;
797805
}
@@ -857,7 +865,21 @@ private EntityHandle GetHandleForMember(MemberInfo member)
857865
}
858866

859867
private static bool IsConstructedFromNotBakedTypeBuilder(Type type) => type.IsConstructedGenericType &&
860-
type.GetGenericTypeDefinition() is TypeBuilderImpl tb && tb._handle == default;
868+
(type.GetGenericTypeDefinition() is TypeBuilderImpl tb && tb._handle == default) ||
869+
ContainsNotBakedTypeBuilder(type.GetGenericArguments());
870+
871+
private static bool ContainsNotBakedTypeBuilder(Type[] genericArguments)
872+
{
873+
foreach (Type type in genericArguments)
874+
{
875+
if (type is TypeBuilderImpl tb && tb._handle == default)
876+
{
877+
return true;
878+
}
879+
}
880+
881+
return false;
882+
}
861883

862884
public override int GetMethodMetadataToken(ConstructorInfo constructor) => GetTokenForHandle(GetConstructorHandle(constructor));
863885

@@ -880,6 +902,11 @@ internal EntityHandle GetMethodHandle(MethodInfo method)
880902
return mb._handle;
881903
}
882904

905+
if (IsConstructedMethodFromNotBakedMethodBuilder(method))
906+
{
907+
return default;
908+
}
909+
883910
return GetHandleForMember(method);
884911
}
885912

src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ParameterBuilderImpl.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@ public ParameterBuilderImpl(MethodBuilderImpl methodBuilder, int sequence, Param
3030

3131
public override int Position => _position;
3232

33-
public override void SetConstant(object? defaultValue) => _defaultValue = defaultValue;
33+
public override void SetConstant(object? defaultValue)
34+
{
35+
FieldBuilderImpl.ValidateDefaultValueType(defaultValue, _methodBuilder.ParameterTypes![_position - 1]);
36+
_defaultValue = defaultValue;
37+
_attributes |= ParameterAttributes.HasDefault;
38+
}
3439

3540
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
3641
{

src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs

Lines changed: 70 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,20 @@ private void ValidateAllAbstractMethodsAreImplemented()
191191
}
192192

193193
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2065:DynamicallyAccessedMembers", Justification = "Methods are loaded from this TypeBuilder. The interface methods should be available at this point")]
194+
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:DynamicallyAccessedMembers", Justification =
195+
"Somehow #pragma warning disable IL2075 doesn't suppress anymore, related to https://github.com/dotnet/runtime/issues/96646")]
194196
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2085:DynamicallyAccessedMembers", Justification = "Methods are loaded from this TypeBuilder")]
195197
private void CheckInterfaces(Type[] _interfaces)
196198
{
197199
foreach (Type interfaceType in _interfaces)
198200
{
199-
#pragma warning disable IL2075 // Analyzer produces a different warning code than illink. The IL2065 suppression takes care of illink: https://github.com/dotnet/runtime/issues/96646
200-
MethodInfo[] interfaceMethods = interfaceType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
201-
#pragma warning restore IL2075
201+
Type ifaceType = interfaceType;
202+
if (interfaceType.IsConstructedGenericType &&
203+
IsConstructedFromTypeBuilder(interfaceType.GetGenericTypeDefinition(), interfaceType.GetGenericArguments()))
204+
{
205+
ifaceType = interfaceType.GetGenericTypeDefinition();
206+
}
207+
MethodInfo[] interfaceMethods = ifaceType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
202208
for (int i = 0; i < interfaceMethods.Length; i++)
203209
{
204210
MethodInfo interfaceMethod = interfaceMethods[i];
@@ -207,7 +213,9 @@ private void CheckInterfaces(Type[] _interfaces)
207213
continue;
208214
}
209215

210-
MethodInfo? implementedMethod = GetMethodImpl(interfaceMethod.Name, GetBindingFlags(interfaceMethod), null, interfaceMethod.CallingConvention, GetParameterTypes(interfaceMethod.GetParameters()), null);
216+
Type[] parameterTypes = interfaceMethod.ContainsGenericParameters ?
217+
GetParameterTypesMatchGeneric(interfaceMethod.GetParameters(), interfaceType.GetGenericArguments()) : GetParameterTypes(interfaceMethod.GetParameters());
218+
MethodInfo? implementedMethod = GetMethodImpl(interfaceMethod.Name, GetBindingFlags(interfaceMethod), null, interfaceMethod.CallingConvention, parameterTypes, null);
211219

212220
if ((implementedMethod == null || implementedMethod.IsAbstract) && !FoundInInterfaceMapping(interfaceMethod))
213221
{
@@ -216,12 +224,28 @@ private void CheckInterfaces(Type[] _interfaces)
216224
}
217225

218226
// Check parent interfaces too
219-
#pragma warning disable IL2075 // Analyzer produces a different warning code than illink. The IL2065 suppression takes care of illink: https://github.com/dotnet/runtime/issues/96646
220-
CheckInterfaces(interfaceType.GetInterfaces());
221-
#pragma warning restore IL2075
227+
CheckInterfaces(ifaceType.GetInterfaces());
222228
}
223229
}
224230

231+
private static bool IsConstructedFromTypeBuilder(Type constructedType, Type[] genericArgs)
232+
{
233+
if (constructedType is TypeBuilderImpl)
234+
{
235+
return true;
236+
}
237+
238+
foreach (Type arg in genericArgs)
239+
{
240+
if (arg is TypeBuilderImpl or GenericTypeParameterBuilderImpl)
241+
{
242+
return true;
243+
}
244+
}
245+
246+
return false;
247+
}
248+
225249
private bool FoundInInterfaceMapping(MethodInfo abstractMethod)
226250
{
227251
if (_methodOverrides == null)
@@ -836,8 +860,6 @@ internal static BindingFlags GetBindingFlags(MethodInfo method)
836860

837861
private static bool MatchesTheFilter(MethodBuilderImpl method, BindingFlags methodFlags, BindingFlags bindingFlags, CallingConventions callConv, Type[]? argumentTypes)
838862
{
839-
bindingFlags ^= BindingFlags.DeclaredOnly;
840-
841863
if ((bindingFlags & methodFlags) != methodFlags)
842864
{
843865
return false;
@@ -977,19 +999,17 @@ public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
977999
}
9781000

9791001
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
980-
public override FieldInfo? GetField(string name, BindingFlags bindingAttr)
1002+
public override FieldInfo? GetField(string name, BindingFlags bindingFlags)
9811003
{
9821004
ArgumentNullException.ThrowIfNull(name);
1005+
ThrowIfNotCreated();
9831006

9841007
FieldInfo? match = null;
985-
986-
BindingFlags fieldFlags = bindingAttr ^ BindingFlags.DeclaredOnly;
987-
fieldFlags ^= BindingFlags.IgnoreCase;
988-
StringComparison compare = (bindingAttr & BindingFlags.IgnoreCase) != 0 ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
1008+
StringComparison compare = (bindingFlags & BindingFlags.IgnoreCase) != 0 ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
9891009
foreach (FieldBuilderImpl fieldInfo in _fieldDefinitions)
9901010
{
991-
BindingFlags currentFieldFlags = GetBindingFlags(fieldInfo);
992-
if (name.Equals(fieldInfo.Name, compare) && (fieldFlags & currentFieldFlags) == currentFieldFlags)
1011+
BindingFlags fieldFlags = GetBindingFlags(fieldInfo);
1012+
if (name.Equals(fieldInfo.Name, compare) && (bindingFlags & fieldFlags) == fieldFlags)
9931013
{
9941014
if (match != null)
9951015
{
@@ -1003,9 +1023,9 @@ public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
10031023
}
10041024
}
10051025

1006-
if (match == null && !bindingAttr.HasFlag(BindingFlags.DeclaredOnly) && _typeParent != null)
1026+
if (match == null && !bindingFlags.HasFlag(BindingFlags.DeclaredOnly) && _typeParent != null)
10071027
{
1008-
match = _typeParent.GetField(name, bindingAttr);
1028+
match = _typeParent.GetField(name, bindingFlags);
10091029
}
10101030

10111031
return match;
@@ -1022,7 +1042,23 @@ private static BindingFlags GetBindingFlags(FieldBuilderImpl field)
10221042
}
10231043

10241044
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
1025-
public override FieldInfo[] GetFields(BindingFlags bindingAttr) => throw new NotSupportedException();
1045+
public override FieldInfo[] GetFields(BindingFlags bindingAttr)
1046+
{
1047+
ThrowIfNotCreated();
1048+
1049+
List<FieldBuilderImpl> candidates = new List<FieldBuilderImpl>(_fieldDefinitions.Count);
1050+
for (int i = 0; i < _fieldDefinitions.Count; i++)
1051+
{
1052+
FieldBuilderImpl fieldInfo = _fieldDefinitions[i];
1053+
BindingFlags fieldFlags = GetBindingFlags(fieldInfo);
1054+
if ((bindingAttr & fieldFlags) == fieldFlags)
1055+
{
1056+
candidates.Add(fieldInfo);
1057+
}
1058+
}
1059+
1060+
return candidates.ToArray();
1061+
}
10261062

10271063
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
10281064
[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
@@ -1105,6 +1141,21 @@ private static Type[] GetParameterTypes(ParameterInfo[] parameterInfos)
11051141
return parameterTypes;
11061142
}
11071143

1144+
private static Type[] GetParameterTypesMatchGeneric(ParameterInfo[] parameters, Type[] genericArguments)
1145+
{
1146+
Type[] parameterTypes = new Type[parameters.Length];
1147+
for (int i = 0; i < parameters.Length; i++)
1148+
{
1149+
parameterTypes[i] = parameters[i].ParameterType;
1150+
if (parameterTypes[i].IsGenericParameter)
1151+
{
1152+
parameterTypes[i] = genericArguments[parameterTypes[i].GenericParameterPosition];
1153+
}
1154+
}
1155+
1156+
return parameterTypes;
1157+
}
1158+
11081159
private void ValidateInterfaceType(Type interfaceType)
11091160
{
11101161
if (!interfaceType.IsInterface)

src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveCustomAttributeTests.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,6 @@ private static void DefineMethodsAndSetAttributes(List<CustomAttributeBuilder> m
171171
{
172172
ParameterBuilder pb = meb.DefineParameter(param.Position + 1, param.Attributes, param.Name);
173173
paramAttributes.ForEach(pb.SetCustomAttribute);
174-
if (param.ParameterType.Equals(typeof(string)))
175-
{
176-
pb.SetConstant("Hello");
177-
}
178174
}
179175
}
180176
}

0 commit comments

Comments
 (0)