[Not a bug or issue, need some help purely underst...
# general
l
[Not a bug or issue, need some help purely understanding something] Hi, I've been systematically going through the docs like a textbook (the docs are lovely) and trying to test if I understand against existing code. I am stumped and would appreciate some guidance. For the recurring example of ShellCheck as a linter in the docs, I cannot figure out how:
Copy code
all_batch_results = await MultiGet(
        Get(LintResult, AbstractLintRequest.Batch, request) for request in batches
    )
in the lint goal_rule ultimately ends up deferring to the rule that presumably calculates lintresults for shellcheck:
Copy code
@rule(desc="Lint with Shellcheck", level=LogLevel.DEBUG)
async def run_shellcheck(
    request: ShellcheckRequest.Batch[ShellcheckFieldSet, Any],
    shellcheck: Shellcheck,
    platform: Platform,
) -> LintResult:
• Does the above
Get
not end up calling this rule? • is there some mechanism available because ShellcheckRequest.Batch is part of a union under AbstractLintRequest.Batch? If so where do we get the Platform needed for the rule given that it is not in the original Get?
b
• It does • Yes, precisely. The rest of a rule's arguments are filled by the graph traversing from roots that it knows. E.g. Platform is calculatable from the global options, or the world itself.
l
Oh - does that mean that under the hood the engine checks the runtime type of the
request
object and notices that it is a
ShellcheckRequest.Batch
and looks for a route to
LintResult
from there?
Where would I go to find the code that handles this generic capability? (is it on the rust side or the python side?)
b
Somewhere in the engine, I presume. Where it handles unions
l
Thank you, will have to dig.
g
https://www.pantsbuild.org/docs/rules-api-unions might be informative if you haven't reached that point yet!
l
I had read it, but it did not make clear that this behavior was going to happen. That bit of the docs seemed to only show unions as a mechanism for retrieving a list of types grouped under another type (via unionmembership.get), not the implications at the Get level. The doc-string for
@union
does give an indication, though:
Annotating a class with @union allows other classes to register a
UnionRule(BaseClass, MemberClass)
. Then, you can use
await Get(Output, UnionBase, concrete_union_member)
. This would be similar to writing
UnionRule(Output, ConcreteUnionMember, concrete_union_member_instance)
, but allows you to write generic code without knowing what concrete classes might later implement that union.