Skip to content

Compiler-generated code analysis relies on definite assignment #2871

@sbomer

Description

@sbomer

#2842 tracks assignments to hoisted locals within a group of compiler-generated methods. It uses Top as the default value for hoisted locals, instead of UnknownValue.Instance, to avoid excess warnings.

Consider this example:

using System;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
public class C {
    public static IEnumerable<int> M(Type unknownType) {
        yield return 0;
        RequireAll(unknownType);
    }
    
    static void RequireAll([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type t) {}
}

The compiler generates two fields on the state machine type, unknownType and <>3__unknownType:

  • M assigns <>3__unknownType from the method parameter
  • GetEnumerator assigns unknownType from <>3__unknownType
  • MoveNext reads unknownType

If the default value were UnknownValue.Instance, we would get an extra warning (unknown value passed to RequireAll). To prevent this we currently rely on definite assignment, which should guarantee that some assigned value reaches the point of consumption, so Top shouldn't be an analysis hole.

But as @vitek-karas pointed out in #2842 (comment), we would ideally not rely on this for general IL analysis. We could potentially improve this by making the default value UnknownValue.Instance, but analyzing state machine methods in a specific order so that assignments override the default unknown value. It would mean making the analysis flow-sensitive instead of tracking all assigned values (similar for nested functions).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions