Skip to content

Commit efb09a5

Browse files
authored
Fix warning for MakeGenericType annotation mismatch (#104921)
Fixes warning code when a generic type whose type parameters have DAM annotations is used with MakeGenericType, over a type that doesn't have matching annotations. The code IL2070 used to mention the 'this' argument. Instead it should have been IL2071 which mentions the generic argument as the cause of the mismatch. Similar for MakeGenericMethod with IL2090 and IL2091.
1 parent e75fc27 commit efb09a5

File tree

16 files changed

+80
-84
lines changed

16 files changed

+80
-84
lines changed

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
@@ -958,6 +958,11 @@ internal partial MethodReturnValue GetMethodReturnValue(MethodProxy method, bool
958958
internal partial MethodReturnValue GetMethodReturnValue(MethodProxy method, bool isNewObj)
959959
=> GetMethodReturnValue(method, isNewObj, GetReturnParameterAnnotation(method.Method));
960960

961+
#pragma warning disable CA1822 // Other partial implementations are not in the ilc project
962+
internal partial GenericParameterValue GetGenericParameterValue(GenericParameterProxy genericParameter, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
963+
#pragma warning restore CA1822 // Mark members as static
964+
=> new GenericParameterValue(genericParameter.GenericParameter, dynamicallyAccessedMemberTypes);
965+
961966
internal partial GenericParameterValue GetGenericParameterValue(GenericParameterProxy genericParameter)
962967
=> new GenericParameterValue(genericParameter.GenericParameter, GetGenericParameterAnnotation(genericParameter.GenericParameter));
963968

@@ -970,18 +975,14 @@ internal partial MethodParameterValue GetMethodParameterValue(ParameterProxy par
970975
=> GetMethodParameterValue(param, GetParameterAnnotation(param));
971976

972977
#pragma warning disable CA1822 // Mark members as static - Should be an instance method for consistency
973-
// overrideIsThis is needed for backwards compatibility with MakeGenericType/Method https://github.com/dotnet/linker/issues/2428
974-
internal MethodParameterValue GetMethodThisParameterValue(MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes, bool overrideIsThis = false)
978+
internal partial MethodParameterValue GetMethodThisParameterValue(MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
975979
{
976-
if (!method.HasImplicitThis() && !overrideIsThis)
980+
if (!method.HasImplicitThis())
977981
throw new InvalidOperationException($"Cannot get 'this' parameter of method {method.GetDisplayName()} with no 'this' parameter.");
978-
return new MethodParameterValue(new ParameterProxy(method, (ParameterIndex)0), dynamicallyAccessedMemberTypes, overrideIsThis);
982+
return new MethodParameterValue(new ParameterProxy(method, (ParameterIndex)0), dynamicallyAccessedMemberTypes);
979983
}
980984
#pragma warning restore CA1822 // Mark members as static
981985

982-
internal partial MethodParameterValue GetMethodThisParameterValue(MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
983-
=> GetMethodThisParameterValue(method, dynamicallyAccessedMemberTypes, false);
984-
985986
internal partial MethodParameterValue GetMethodThisParameterValue(MethodProxy method)
986987
{
987988
if (!method.HasImplicitThis())

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodParameterValue.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@ namespace ILLink.Shared.TrimAnalysis
1414
/// </summary>
1515
internal partial record MethodParameterValue
1616
{
17-
public MethodParameterValue(ParameterProxy param, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes, bool overrideIsThis = false)
17+
public MethodParameterValue(ParameterProxy param, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
1818
{
1919
StaticType = param.ParameterType;
2020
Parameter = param;
2121
DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes;
22-
_overrideIsThis = overrideIsThis;
2322
}
2423

2524
public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; }

src/libraries/System.Data.Common/src/System/Data/DataRowExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ private static class UnboxT<T>
155155
}
156156
return NonNullableField;
157157

158-
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2090:MakeGenericMethod",
158+
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2091:MakeGenericMethod",
159159
Justification = "'NullableField<TElem> where TElem : struct' implies 'TElem : new()'. Nullable does not make use of new() so it is safe." +
160160
"The warning is only issued when IsDynamicCodeSupported is true.")]
161161
static Func<object, T?> CreateWhenDynamicCodeSupported()

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverterFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public static JsonConverter<T> Create<T>(EnumConverterOptions converterOptions,
4646
}
4747

4848
[RequiresDynamicCode(JsonSerializer.SerializationRequiresDynamicCodeMessage)]
49-
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
49+
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2071:UnrecognizedReflectionPattern",
5050
Justification = "'EnumConverter<T> where T : struct' implies 'T : new()', so the trimmer is warning calling MakeGenericType here because enumType's constructors are not annotated. " +
5151
"But EnumConverter doesn't call new T(), so this is safe.")]
5252
public static JsonConverter Create(Type enumType, EnumConverterOptions converterOptions, JsonNamingPolicy? namingPolicy, JsonSerializerOptions options)

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/NullableConverterFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public static JsonConverter CreateValueConverter(Type valueTypeToConvert, JsonCo
4343
culture: null)!;
4444
}
4545

46-
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
46+
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2071:UnrecognizedReflectionPattern",
4747
Justification = "'NullableConverter<T> where T : struct' implies 'T : new()', so the trimmer is warning calling MakeGenericType here because valueTypeToConvert's constructors are not annotated. " +
4848
"But NullableConverter doesn't call new T(), so this is safe.")]
4949
[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]

src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/FlowAnnotations.cs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, boo
109109
internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, bool isNewObj)
110110
=> GetMethodReturnValue (method, isNewObj, GetMethodReturnValueAnnotation (method.Method));
111111

112+
internal partial GenericParameterValue GetGenericParameterValue (GenericParameterProxy genericParameter, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
113+
=> new GenericParameterValue (genericParameter.TypeParameterSymbol, dynamicallyAccessedMemberTypes);
114+
112115
internal partial GenericParameterValue GetGenericParameterValue (GenericParameterProxy genericParameter)
113116
=> new GenericParameterValue (genericParameter.TypeParameterSymbol);
114117

@@ -119,14 +122,6 @@ internal partial MethodParameterValue GetMethodThisParameterValue (MethodProxy m
119122
return GetMethodParameterValue (new ParameterProxy (method, (ParameterIndex) 0), dynamicallyAccessedMemberTypes);
120123
}
121124

122-
// overrideIsThis is needed for backwards compatibility with MakeGenericType/Method https://github.com/dotnet/linker/issues/2428
123-
internal MethodParameterValue GetMethodThisParameterValue (MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes, bool overrideIsThis = false)
124-
{
125-
if (!method.HasImplicitThis () && !overrideIsThis)
126-
throw new InvalidOperationException ($"Cannot get 'this' parameter of method {method.GetDisplayName ()} with no 'this' parameter.");
127-
return new MethodParameterValue (new ParameterProxy (method, (ParameterIndex) 0), dynamicallyAccessedMemberTypes, overrideIsThis);
128-
}
129-
130125
internal partial MethodParameterValue GetMethodThisParameterValue (MethodProxy method)
131126
{
132127
if (!method.HasImplicitThis ())

src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/GenericParameterValue.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,18 @@ namespace ILLink.Shared.TrimAnalysis
1515
/// </summary>
1616
internal partial record GenericParameterValue
1717
{
18-
public GenericParameterValue (ITypeParameterSymbol typeParameterSymbol) => GenericParameter = new (typeParameterSymbol);
18+
public GenericParameterValue (ITypeParameterSymbol typeParameterSymbol, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
19+
{
20+
GenericParameter = new (typeParameterSymbol);
21+
DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes;
22+
}
1923

20-
public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes => GenericParameter.TypeParameterSymbol.GetDynamicallyAccessedMemberTypes ();
24+
public GenericParameterValue (ITypeParameterSymbol typeParameterSymbol)
25+
: this (typeParameterSymbol, typeParameterSymbol.GetDynamicallyAccessedMemberTypes ())
26+
{
27+
}
28+
29+
public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; }
2130

2231
public override IEnumerable<string> GetDiagnosticArgumentsForAnnotationMismatch ()
2332
=> new string[] { GenericParameter.TypeParameterSymbol.Name, GenericParameter.TypeParameterSymbol.ContainingSymbol.GetDisplayName () };

src/tools/illink/src/ILLink.RoslynAnalyzer/TrimAnalysis/MethodParameterValue.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@ public MethodParameterValue (IMethodSymbol methodSymbol, ParameterIndex paramete
1717
public MethodParameterValue (ParameterProxy parameter)
1818
: this (parameter, FlowAnnotations.GetMethodParameterAnnotation (parameter)) { }
1919

20-
public MethodParameterValue (ParameterProxy parameter, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes, bool overrideIsThis = false)
20+
public MethodParameterValue (ParameterProxy parameter, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
2121
{
2222
Parameter = parameter;
2323
DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes;
2424
StaticType = parameter.ParameterType;
25-
_overrideIsThis = overrideIsThis;
2625
}
2726

2827
public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; }

src/tools/illink/src/ILLink.Shared/TrimAnalysis/FlowAnnotations.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ partial class FlowAnnotations
2525

2626
internal partial GenericParameterValue GetGenericParameterValue (GenericParameterProxy genericParameter);
2727

28+
internal partial GenericParameterValue GetGenericParameterValue (GenericParameterProxy genericParameter, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes);
29+
2830
internal partial MethodParameterValue GetMethodThisParameterValue (MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes);
2931

3032
internal partial MethodParameterValue GetMethodThisParameterValue (MethodProxy method);

src/tools/illink/src/ILLink.Shared/TrimAnalysis/HandleCallAction.cs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,7 @@ ValueWithDynamicallyAccessedMembers valueWithDynamicallyAccessedMembers
909909
} else {
910910
// Any other type - perform generic parameter validation
911911
var genericParameterValues = GetGenericParameterValues (typeValue.RepresentedType.GetGenericParameters ());
912-
if (!AnalyzeGenericInstantiationTypeArray (argumentValues[0], calledMethod, genericParameterValues)) {
912+
if (!AnalyzeGenericInstantiationTypeArray (argumentValues[0], genericParameterValues)) {
913913
_diagnosticContext.AddDiagnostic (DiagnosticId.MakeGenericType, calledMethod.GetDisplayName ());
914914
}
915915
}
@@ -1242,7 +1242,7 @@ private IEnumerable<MultiValue> ProcessGetMethodByName (TypeProxy type, string m
12421242
yield return NullValue.Instance;
12431243
}
12441244

1245-
private bool AnalyzeGenericInstantiationTypeArray (in MultiValue arrayParam, in MethodProxy calledMethod, ImmutableArray<GenericParameterValue> genericParameters)
1245+
private bool AnalyzeGenericInstantiationTypeArray (in MultiValue arrayParam, ImmutableArray<GenericParameterValue> genericParameters)
12461246
{
12471247
bool hasRequirements = false;
12481248
foreach (var genericParameter in genericParameters) {
@@ -1280,10 +1280,7 @@ private bool AnalyzeGenericInstantiationTypeArray (in MultiValue arrayParam, in
12801280

12811281
for (int i = 0; i < size.Value; i++) {
12821282
if (array.TryGetValueByIndex (i, out MultiValue value)) {
1283-
// https://github.com/dotnet/linker/issues/2428
1284-
// We need to report the target as "this" - as that was the previous behavior
1285-
// but with the annotation from the generic parameter.
1286-
var targetValue = _annotations.GetMethodThisParameterValue (calledMethod, GetGenericParameterEffectiveMemberTypes (genericParameters[i]), overrideIsThis: true);
1283+
var targetValue = _annotations.GetGenericParameterValue (genericParameters[i].GenericParameter, GetGenericParameterEffectiveMemberTypes (genericParameters[i]));
12871284
_requireDynamicallyAccessedMembersAction.Invoke (value, targetValue);
12881285
}
12891286
}
@@ -1315,7 +1312,7 @@ private void ValidateGenericMethodInstantiation (
13151312
}
13161313

13171314
var genericParameterValues = GetGenericParameterValues (genericMethod.GetGenericParameters ());
1318-
if (!AnalyzeGenericInstantiationTypeArray (genericParametersArray, reflectionMethod, genericParameterValues)) {
1315+
if (!AnalyzeGenericInstantiationTypeArray (genericParametersArray, genericParameterValues)) {
13191316
_diagnosticContext.AddDiagnostic (DiagnosticId.MakeGenericMethod, reflectionMethod.GetDisplayName ());
13201317
}
13211318
}

src/tools/illink/src/ILLink.Shared/TrimAnalysis/MethodParameterValue.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ namespace ILLink.Shared.TrimAnalysis
1313
{
1414
internal sealed partial record MethodParameterValue : ValueWithDynamicallyAccessedMembers, IValueWithStaticType
1515
{
16-
// _overrideIsThis is needed for backwards compatibility with MakeGenericType/Method https://github.com/dotnet/linker/issues/2428
17-
private readonly bool _overrideIsThis;
18-
1916
public TypeProxy? StaticType { get; }
2017

2118
public ParameterProxy Parameter { get; }
@@ -26,7 +23,7 @@ public override IEnumerable<string> GetDiagnosticArgumentsForAnnotationMismatch
2623
public override string ToString ()
2724
=> this.ValueToString (Parameter.Method.Method, Parameter.Index, DynamicallyAccessedMemberTypes);
2825

29-
public bool IsThisParameter () => _overrideIsThis || Parameter.IsImplicitThis;
26+
public bool IsThisParameter () => Parameter.IsImplicitThis;
3027

3128
public override SingleValue DeepCopy () => this; // This value is immutable
3229

src/tools/illink/src/linker/Linker.Dataflow/FlowAnnotations.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,11 @@ internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, boo
693693
internal partial MethodReturnValue GetMethodReturnValue (MethodProxy method, bool isNewObj)
694694
=> GetMethodReturnValue (method, isNewObj, GetReturnParameterAnnotation (method.Method));
695695

696+
#pragma warning disable CA1822 // Mark members as static - Should be an instance method for consistency
697+
internal partial GenericParameterValue GetGenericParameterValue (GenericParameterProxy genericParameter, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
698+
=> new GenericParameterValue (genericParameter.GenericParameter, dynamicallyAccessedMemberTypes);
699+
#pragma warning restore CA1822 // Mark members as static
700+
696701
internal partial GenericParameterValue GetGenericParameterValue (GenericParameterProxy genericParameter)
697702
=> new GenericParameterValue (genericParameter.GenericParameter, GetGenericParameterAnnotation (genericParameter.GenericParameter));
698703

@@ -703,18 +708,14 @@ internal partial MethodParameterValue GetMethodParameterValue (ParameterProxy pa
703708
=> GetMethodParameterValue (param, GetParameterAnnotation (param));
704709

705710
#pragma warning disable CA1822 // Mark members as static - Should be an instance method for consistency
706-
// overrideIsThis is needed for backwards compatibility with MakeGenericType/Method https://github.com/dotnet/linker/issues/2428
707-
internal MethodParameterValue GetMethodThisParameterValue (MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes, bool overrideIsThis = false)
711+
internal partial MethodParameterValue GetMethodThisParameterValue (MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
708712
{
709-
if (!method.HasImplicitThis () && !overrideIsThis)
713+
if (!method.HasImplicitThis ())
710714
throw new InvalidOperationException ($"Cannot get 'this' parameter of method {method.GetDisplayName ()} with no 'this' parameter.");
711-
return new MethodParameterValue (method.Method.DeclaringType, new ParameterProxy (method, (ParameterIndex) 0), dynamicallyAccessedMemberTypes, overrideIsThis);
715+
return new MethodParameterValue (method.Method.DeclaringType, new ParameterProxy (method, (ParameterIndex) 0), dynamicallyAccessedMemberTypes);
712716
}
713717
#pragma warning restore CA1822 // Mark members as static
714718

715-
internal partial MethodParameterValue GetMethodThisParameterValue (MethodProxy method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
716-
=> GetMethodThisParameterValue (method, dynamicallyAccessedMemberTypes, false);
717-
718719
internal partial MethodParameterValue GetMethodThisParameterValue (MethodProxy method)
719720
{
720721
if (!method.HasImplicitThis ())

src/tools/illink/src/linker/Linker.Dataflow/MethodParameterValue.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@ namespace ILLink.Shared.TrimAnalysis
1515
/// </summary>
1616
internal partial record MethodParameterValue
1717
{
18-
public MethodParameterValue (TypeDefinition? staticType, ParameterProxy param, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes, bool overrideIsThis = false)
18+
public MethodParameterValue (TypeDefinition? staticType, ParameterProxy param, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
1919
{
2020
StaticType = staticType == null ? null : new (staticType);
2121
DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes;
2222
Parameter = param;
23-
_overrideIsThis = overrideIsThis;
2423
}
2524

2625
public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; }

src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/AnnotatedMembersAccessedViaReflection.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -739,8 +739,7 @@ static void DynamicallyAccessedMembers ()
739739
typeof (AnnotatedGenerics).RequiresPublicMethods ();
740740
}
741741

742-
// This should produce IL2071 https://github.com/dotnet/linker/issues/2144
743-
[ExpectedWarning ("IL2070", "MakeGenericMethod")]
742+
[ExpectedWarning ("IL2071", "'T'")]
744743
static void InstantiateGeneric (Type type = null)
745744
{
746745
// This should warn due to MakeGenericMethod - in this case the generic parameter is unannotated type

0 commit comments

Comments
 (0)