Observation
SPEC-004 §3.1.1 states that several matching [target.<selector>.<section>] tables apply in manifest order, the later one replacing the earlier one. §9 item 2 states that vectors are appended in the order of the matching [target.<selector>.build] tables. The implementation does not follow either statement:
modules/manifest/src/toml.cppm builds conditionalConfigs by iterating a TOML table.
mcpp.libs.toml's Table is std::map<std::string, Value, std::less<>>, so the iteration is in the lexical order of the selector text, not in source order (modules/libs/src/toml.cppm: "Key order carries no meaning in TOML").
For a manifest in which two selectors both match, and both state the same dependency or the same scalar, the table whose selector sorts later wins, whatever its position in the file. Vectors are appended in that order too. Every conditional key is affected. The mismatch was found while implementing #717, whose unit test first asserted manifest order and failed.
Why this is not only an implementation defect
TOML gives the keys of a table no order, so a rule that depends on source order cannot be implemented by a conforming TOML reader. The specification has to state an order that the data model carries, or refuse the ambiguous case.
Options
- Refuse a conflict between two matching rows. When two matching rows state the same identity or scalar with different values, refuse the manifest and name both selectors. Vectors from several matching rows are appended in a stated, documented order, for example the lexical order of the selector.
- State lexical selector order as the rule. This is deterministic, but it makes the answer depend on how a selector is spelled.
Option 1 matches SPEC-004 §4.4 (a condition is not written twice) and the refusal of contradictory statements elsewhere.
Observation
SPEC-004 §3.1.1 states that several matching
[target.<selector>.<section>]tables apply in manifest order, the later one replacing the earlier one. §9 item 2 states that vectors are appended in the order of the matching[target.<selector>.build]tables. The implementation does not follow either statement:modules/manifest/src/toml.cppmbuildsconditionalConfigsby iterating a TOML table.mcpp.libs.toml'sTableisstd::map<std::string, Value, std::less<>>, so the iteration is in the lexical order of the selector text, not in source order (modules/libs/src/toml.cppm: "Key order carries no meaning in TOML").For a manifest in which two selectors both match, and both state the same dependency or the same scalar, the table whose selector sorts later wins, whatever its position in the file. Vectors are appended in that order too. Every conditional key is affected. The mismatch was found while implementing #717, whose unit test first asserted manifest order and failed.
Why this is not only an implementation defect
TOML gives the keys of a table no order, so a rule that depends on source order cannot be implemented by a conforming TOML reader. The specification has to state an order that the data model carries, or refuse the ambiguous case.
Options
Option 1 matches SPEC-004 §4.4 (a condition is not written twice) and the refusal of contradictory statements elsewhere.