Skip to content

Commit ea94440

Browse files
authored
Fix mapping of redeclared type parameters (#86353)
We were skipping the type parameter mapping of compiler-generated types whose only generic parameters were those implicitly created for the declaring type's type parameters. For the testcase in question, the nested state machine inherited a generic parameter from the display class. This was causing unnecessary warnings in a field assignment that assigned `this` (an instance of the display class) to a field on the state machine. In IL, that assignment references a field type like `DisplayClass<T>` where `T` is the generic parameter on the state machine. Here we were properly mapping type parameters of the display class back to the annotated enclosing method's type parameters, so we could tell that the "target" required `PublicMethods`. But the substituted `T` from the state machine was not mapped, causing the mismatch.
1 parent 3924920 commit ea94440

File tree

3 files changed

+19
-28
lines changed

3 files changed

+19
-28
lines changed

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

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -288,24 +288,11 @@ referencedMethod.OwningType is MetadataType generatedType &&
288288
{
289289
Debug.Assert(generatedType == generatedType.GetTypeDefinition());
290290

291-
if (HasGenericParameters(generatedType))
291+
if (generatedType.HasInstantiation)
292292
MapGeneratedTypeTypeParameters(generatedType);
293293
}
294294
}
295295

296-
/// <summary>
297-
/// Check if the type itself is generic. The only difference is that
298-
/// if the type is a nested type, the generic parameters from its
299-
/// parent type don't count.
300-
/// </summary>
301-
static bool HasGenericParameters(MetadataType typeDef)
302-
{
303-
if (typeDef.ContainingType == null)
304-
return typeDef.HasInstantiation;
305-
306-
return typeDef.Instantiation.Length > typeDef.ContainingType.Instantiation.Length;
307-
}
308-
309296
void MapGeneratedTypeTypeParameters(MetadataType generatedType)
310297
{
311298
Debug.Assert(CompilerGeneratedNames.IsGeneratedType(generatedType.Name));

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

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ referencedMethod.DeclaringType is var generatedType &&
283283
// Now that we have instantiating methods fully filled out, walk the generated types and fill in the attribute
284284
// providers
285285
foreach (var generatedType in generatedTypeToTypeArgs.Keys) {
286-
if (HasGenericParameters (generatedType)) {
286+
if (generatedType.HasGenericParameters) {
287287
MapGeneratedTypeTypeParameters (generatedType, generatedTypeToTypeArgs, _context);
288288
// Finally, add resolved type arguments to the cache
289289
var info = generatedTypeToTypeArgs[generatedType];
@@ -298,19 +298,6 @@ referencedMethod.DeclaringType is var generatedType &&
298298
_cachedTypeToCompilerGeneratedMembers.Add (type, compilerGeneratedCallees);
299299
return type;
300300

301-
/// <summary>
302-
/// Check if the type itself is generic. The only difference is that
303-
/// if the type is a nested type, the generic parameters from its
304-
/// parent type don't count.
305-
/// </summary>
306-
static bool HasGenericParameters (TypeDefinition typeDef)
307-
{
308-
if (!typeDef.IsNested)
309-
return typeDef.HasGenericParameters;
310-
311-
return typeDef.GenericParameters.Count > typeDef.DeclaringType.GenericParameters.Count;
312-
}
313-
314301
/// <summary>
315302
/// Attempts to reverse the process of the compiler's alpha renaming. So if the original code was
316303
/// something like this:

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public static void Main ()
3232
AsyncCapture ();
3333
AsyncTypeMismatch ();
3434
AsyncInsideClosure ();
35+
AsyncInsideClosureNonGeneric ();
3536
AsyncInsideClosureMismatch ();
3637

3738
// Closures
@@ -220,6 +221,22 @@ private static void AsyncInsideClosure ()
220221
}
221222
}
222223

224+
private static void AsyncInsideClosureNonGeneric ()
225+
{
226+
Outer<string> ();
227+
void Outer<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T1> ()
228+
{
229+
int x = 0;
230+
Inner ().Wait ();
231+
async Task Inner ()
232+
{
233+
await Task.Delay (0);
234+
x++;
235+
_ = typeof (T1).GetMethods ();
236+
}
237+
}
238+
}
239+
223240
private static void AsyncInsideClosureMismatch ()
224241
{
225242
Outer<string> ();

0 commit comments

Comments
 (0)