Skip to content

Binding graph doesn't find references of variables used in tuple assignments #1375

@fvictorio

Description

@fvictorio

Given the following Solidity code:

uint x;
uint y;
(x, y) = (1, 2);

When getting the references of x or y, I get an empty array. This doesn't happen if I do x = 1; y = 2; separately.

Minimal reproduction (change unit.file("works.sol") to unit.file("doesntwork.sol") to see the difference):

import { CompilationBuilder, CompilationUnit } from "@nomicfoundation/slang/compilation";
import { NonterminalKind, TerminalKind } from "@nomicfoundation/slang/cst";
import { LanguageFacts } from "@nomicfoundation/slang/utils";
import assert from "assert";

export async function buildUnitFromSources(sources: Record<string, string>): Promise<CompilationUnit> {
  const readFile = async (fileId: string): Promise<string | undefined> => {
    return sources[fileId];
  };

  const resolveImport = async (): Promise<string | undefined> => {
    return undefined;
  };

  const builder = CompilationBuilder.create({
    languageVersion: LanguageFacts.latestVersion(),
    readFile,
    resolveImport,
  });

  for (const fileName of Object.keys(sources)) {
    await builder.addFile(fileName);
  }

  return builder.build();
}

async function main() {
  const sources = {
    "works.sol": `
      contract C {
        function f() public {
          uint x;
          uint y;
          x = 1;
          y = 2;
        }
      }
    `,
    "doesntwork.sol": `
      contract C {
        function f() public {
          uint x;
          uint y;
          (x, y) = (1, 2);
        }
      }
    `,
  };

  const unit = await buildUnitFromSources(sources);
  const cursor = unit.file("works.sol")!.createTreeCursor();

  while (cursor.goToNextNonterminalWithKind(NonterminalKind.VariableDeclarationStatement)) {
    const idCursor = cursor.spawn();
    idCursor.goToNextTerminalWithKind(TerminalKind.Identifier);
    if (idCursor.node.unparse() === "x" || idCursor.node.unparse() === "y") {
      const definition = unit.bindingGraph.definitionAt(idCursor);

      const references = definition!.references();
      assert(references.length === 1);
    }
  }


}

main().catch(console.error);

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Status

✅ Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions