Skip to content

Compiler emits incorrect EnC closure data to PDB for nested switch expressions #37232

@tmat

Description

@tmat
using System;
public class C
{
    static int M() 
    {
        return F() switch 
        {
            1 => F() switch
                 {
                     C { P: int p, Q: C { P: int q } } => G(() => p + q),
                     _ => 10
                 },
            C { Q: int s } => G(() => s),
            _ => 0
        };
    }

    object P { get; set; }
    object Q { get; set; }
    static object F() => null;
    static int G(Func<int> f) => 0;
}

A display class is emitted for each switch expression:
image

pdb2xml output:

...
<encLambdaMap>
  <methodOrdinal>0</methodOrdinal>
  <closure offset="59" />
  <closure offset="59" />
  <lambda offset="255" closure="0" />
  <lambda offset="157" closure="1" />
</encLambdaMap>
...

The offset attribute of closure identifies the syntax node that's associated with the closure. This offset must be unique, but in this case the compiler emits the same value - the offset of the outer switch expression node.

The lowering creates a spill sequence with locals defined in the switch expression. The spill sequence node is correctly associated with the switch expression syntax at this point.
Later on SpillSequenceSpiller.VisitSpillSequence takes these locals and puts them in BoundSpillSequenceBuilder. Finally, SpillSequenceSpiller.UpdateStatement creates a new BoundBlock with these locals. The BoundBlock is however no longer associated with the right switch expression syntax node.

See test See test PDBTests.Patterns_SwitchExpression_Closures.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions