Skip to content

A wildcard source is matched against the parsed scripts by path suffix and the first match wins, so two scripts with one relative path make a wildcard-bound base depend on hash iteration order #941

Description

@khatchad

The wildcard-bound base resolution added for #938 matches a wildcard source module against the analysis's registry of parsed scripts by path suffix and takes the first script that matches. When two scripts in one analysis end with the same relative path, a/utils/tf_utils.py and b/utils/tf_utils.py say (two source roots, or a vendored copy beside the original), which one's import bindings are consulted depends on the registry's hash iteration order. A class whose base is written through that wildcard binding could then inherit, or not, across runs of the same program with no input change, which reads as a flake and is a resolution ambiguity. Latent, not observed: every fixture in the repository has one wildcard source per analysis, and the condition needs two with the same relative path.

Where

PythonParser.wildcardBoundRoot (the parser module): for each module the file wildcard-imports, the dotted name is turned into a relative path and every registered script equal to it or ending in / plus it is a candidate, and the loop returns the first candidate that binds the root. The registry is a hash map keyed by script name, so candidate order is iteration order.

Why It Is Recorded Now Rather Than Fixed In The Change That Introduced It

The change's witness set proves the resolution does not depend on the order modules are parsed, with an arm that varies that order and a certificate that the arm can fail. This is a different order, the registry's iteration order, and the arm cannot see it because its fixture has one wildcard source. A general sentence such as "the result does not depend on order" would have covered both, and only the parse-order half is true. So the ambiguity is stated at the method and here, and the two orders are kept apart.

Remedies

The minimal one makes the choice deterministic without resolving the ambiguity: order the candidates (exact match first, then by path) so the same program gives the same answer every run, and log when more than one candidate binds the root. The complete one resolves the wildcard the way the module parser resolves the import itself, against the script the importer actually reaches (its own local-module resolution, path-relative to the importer), so a same-suffix script elsewhere in the analysis is never a candidate. Either should come with a fixture holding two scripts of one relative path under different roots, wildcard-imported from different importers, asserting each importer's class inherits from what its own source binds.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions