-
Notifications
You must be signed in to change notification settings - Fork 8.4k
Description
Filters set by an including binding to select the properties it chooses to inherit are not applied as expected when specifications are inherited indirectly (as in A includes B includes C):
- filters set by A are ignored when B includes C
- if both A and B set property filters, these filters are merged then applied to C, where we instead expect that A will filter the outcome of "B includes C"
Passing the simplest (former) test case is easy, but misleading, as fixing the general (later) case might be more involved. [Edit: Reverting #65221 seems to fix all use cases described in this issue.]
Basics
The simplest test case is:
simple.yaml: a base binding file, specifies some properties at the binding, child-binding and grandchild-binding levelssimple_inherit.yaml: justinclude:sthe base binding file above (without modification nor filter)simple_filter.yaml: top-level binding of the test case, which intends to simply filter the properties it inherits like bellow
include:
- name: simple_inherit.yaml
property-allowlist: [prop-1]
child-binding:
property-allowlist: [child-prop-1]
child-binding:
property-allowlist: [grandchild-prop-1] Here we'd expect to finally get only child-prop-1 at the child-binding level and grandchild-prop-1 at the grandchild-binding level: we instead inherit all properties specified in simple.yaml at these levels.
Although this test case could also be addressed on top of #65221, I'm going to fix it by doing a revert (I'll put the rationale for this in the PR). [Edit: see #80030]
Generalization
But there might be a more general issue (independently of #65221).
In my understanding, when B includes I includes X, the filters set by B to select the properties it chooses to inherit should be deferred until they can be applied to the appropriate input:
- first,
IincludesX, with or without filters - then
BincludesI, applying its own filters on top of the propertiesIinherited fromX
Examples that seem natural:
- if
Bonly allows properties which are not in theallowlistof the intermediary binding file (hereI), we should end with no property at all - if
Bblocks all properties which are in theallowlistof the intermediary binding file, we should end with no property at all
More generally, still IIUC, child-binding filters should compose, not be merged:
- if
Ballows[x1, x3]andIallows[x1, x2],Bshould inherit onlyx1, not[x1, x2, x3] - if
Iallows[x1, x2]andBblocksx2, B should inheritx1, not cause an error by merging theallowlistandblocklistfromBandI("should not specify both 'property-allowlist:' and 'property-blocklist:'") - if
Ballows[x1, x2]andYblocksx2,Bshould inheritx1, not cause an error by merging theallowlistandblocklistfromBandI - if
Bblocksx2andIblocksx3,Bshould inheritx1, not[x1, x3]
This is what I would intuitively expect, assuming it's permitted to set filters in an including binding and in an intermediary included file.
AFAICT, the Zephyr documentation doesn't specifically address the rules that apply to this scenario, but it seems that only filtering simultaneously with an allowlist and a blocklist is explicitly prohibited (Devicetree bindings syntax, Include):
You cannot have a single map element with both property-allowlist and property-blocklist keys.
If this reasoning is correct, implementing it properly seems not obvious to me, it's just not how bindings are initialized: without some design changes we can't compose the filters as we include bindings on top of each other, like B=f1(f2(f3(X))), they're instead merged before use, like in B=(f1xf2xf3)(X).
[Edit: all expectations above are actually honored when #65221 is reverted]
I will also open a PR for this general case, with the corresponding unit tests (doomed to fail), but for now without a fix: I don't see how we could get to B=f1(f2(f3(X))) without rethinking the whole Binding initialization.
[Edit: these unit tests, which are no longer supposed to fail, will be added to #79900 instead.]
Thanks.