/// <summary> /// Get index of deconstruction result or tuple element /// Returns -1 on failure. /// </summary> int FindIndex(ILInstruction inst, out Action <DeconstructInstruction> delayedActions) { delayedActions = null; if (inst.MatchLdLoc(out var v)) { if (!deconstructionResultsLookup.TryGetValue(v, out int index)) { return(-1); } return(index); } if (inst.MatchLdFld(out _, out _)) { if (!TupleTransform.MatchTupleFieldAccess((LdFlda)((LdObj)inst).Target, out var tupleType, out var target, out int index)) { return(-1); } // Item fields are one-based, we use zero-based indexing. index--; // normalize tuple type tupleType = TupleType.FromUnderlyingType(context.TypeSystem, tupleType); if (!target.MatchLdLoca(out v)) { return(-1); } if (this.tupleVariable == null) { this.tupleVariable = v; this.tupleType = (TupleType)tupleType; this.deconstructionResults = new ILVariable[this.tupleType.Cardinality]; } if (this.tupleType.Cardinality < 2) { return(-1); } if (v != tupleVariable || !this.tupleType.Equals(tupleType)) { return(-1); } if (this.deconstructionResults[index] == null) { var freshVar = new ILVariable(VariableKind.StackSlot, this.tupleType.ElementTypes[index]) { Name = "E_" + index }; delayedActions += _ => context.Function.Variables.Add(freshVar); this.deconstructionResults[index] = freshVar; } delayedActions += _ => { inst.ReplaceWith(new LdLoc(this.deconstructionResults[index])); }; return(index); } return(-1); }