Gentoo Archives: gentoo-dev

From: "Michał Górny" <mgorny@g.o>
To: gentoo-dev <gentoo-dev@l.g.o>
Subject: [gentoo-dev] [RFC] Restricting allowed nesting of REQUIRED_USE
Date: Fri, 09 Jun 2017 22:30:35
Message-Id: 1497047407.15114.2.camel@gentoo.org
1 Hi, everyone.
2
3 As you may or may not know, PMS says rather little about REQUIRED_USE
4 [1,2]. The largest past of the definition is shared with other
5 dependency-like specifications [3].
6
7 Similarly to regular dependency specifications, PMS is rather lax in
8 nesting things. While this isn't a major problem for dependencies where
9 the syntax is limited to any-of, all-of and USE-conditional groups
10 (though it already may cause some confusion there), it allows quite
11 a bit of a mayhem with the full set of REQUIRED_USE clauses.
12
13 We have five different kinds of clauses there: any-of, at-most-one-of,
14 exactly-one-of, all-of and USE-conditional. Furthermore, unlike
15 in dependency specifications, the last type is circular with flags
16 enforced by REQUIRED_USE constraints.
17
18 While nesting all of those clauses is technically valid (and can be
19 logically verified), it has no proven usability. As a result, it is
20 either not used at all or has a few use cases which suffer from poor
21 readability and can be easily replaced with *much simpler* constraints.
22 In fact, allowing them is not solving any issues but only introducing
23 more when developers fail at using them.
24
25 I would therefore like to discuss restricting nesting of REQUIRED_USE
26 clauses.
27
28
29 What's my take in this? As you have probably noticed (and stopped
30 reading) I am working with Alexis on solving REQUIRED_USE constraints
31 automatically. We're working towards a few goals: keeping things simple,
32 giving predictable solutions, and being able to automatically validate
33 whether the constraints are solvable.
34
35 While we're near solving almost everything, the complex clauses add
36 unnecessary complexity (both to the spec and to the code) which does not
37 really benefit anyone, and bring solutions that can not be predictable
38 because the clauses are ambiguous by design.
39
40 To avoid adding this complexity, it would be reasonable to ban at least
41 some of the non-useful combinations. This means either banning them
42 completely (in a future EAPI + possibly repoman) so that developers do
43 not even try to use them, or disabling autosolving when they are being
44 used).
45
46
47 Below I have listed the clauses I'd like to ban in a few logical groups,
48 along with explanations and examples.
49
50
51 1. Nested ||, ?? and ^^ groups
52 ------------------------------
53
54 Technically, any level of ||, ?? and ^^ nesting is valid. Practically,
55 any nesting is hardly readable, and could be replaced by something
56 simpler. For a few examples:
57
58 || ( a || ( b c ) ) <-> || ( a b c )
59
60 || ( a ?? ( b c ) ) <-> b? ( c? ( a ) )
61
62 ?? ( ?? ( a b ) c ) <-> !a? ( !c ) !b ( !c )
63
64 ?? ( a || ( b c ) ) <-> a? ( !b !c )
65
66 The 'simpler versions' of those constraints may seem weird but that's
67 only because the constraints themselves are weird as hell and it's hard
68 to tell what the original intent might be. I've skipped ^^ as it is
69 equivalent to the conjunction of || and ??.
70
71 FWICS, we have only two cases of this kind of nesting in ::gentoo:
72
73 A. app-backup/bacula:
74
75 || ( ^^ ( mysql postgres sqlite ) bacula-clientonly )
76
77 which could be written equivalently as:
78
79 !bacula-clientonly? ( ^^ ( mysql postgres sqlite ) )
80
81 B. dev-games/ogre:
82
83 ?? ( gl3plus ( || ( gles2 gles3 ) ) ) gles3? ( gles2 )
84
85 which is completely insane. Per the above examples, it could be replaced
86 e.g. by more predictable:
87
88 gl3plus? ( !gles2 !gles3 ) gles3? ( gles2 )
89
90 To summarize, I don't think we really need or want this kind of nesting.
91 I would therefore want to disallow nesting any of ||, ??, ^^ inside any
92 other of ||, ??, ^^ (including as subexpressions).
93
94
95 2. All-of groups inside ??, ^^
96 ------------------------------
97
98 This one is technically valid and not even hard to solve. However,
99 I haven't found any use case for it and it's impossible to solve it
100 in a completely predictable way.
101
102 Let's take a simple case here:
103
104 ?? ( A ( B C ) )
105
106 The meaning is rather simple: you can't enable both A and (B and C).
107 If we put the preference on A, then this constraint can be solved
108 by either disabling B or C, or both. And there's no definitive answer
109 on what would be the preferred action here.
110
111 So it'd really be better to be clearer on the desired result, e.g.:
112
113 A? ( !B !C )
114 A? ( !B )
115
116 etc. I'm aware that it would become more complex with more clauses;
117 however, nobody has been able to come up with even one so far.
118
119 The only use cases of all-of groups inside ??/^^ in ::gentoo are:
120
121 A. sci-chemistry/icm:
122
123 ^^ ( ( !32bit 64bit ) ( 32bit !64bit ) ( 32bit 64bit ) )
124
125 which is much more readable as:
126
127 || ( 64bit 32bit )
128
129 B. media-sound/snd:
130
131 ^^ ( ( !ruby !s7 ) ( ruby !s7 ) ( !ruby s7 ) )
132
133 which, once again, is much less confusing as:
134
135 ?? ( ruby s7 )
136
137 All that considered, I think this has no real use case and only
138 encourages people to do stupid things. Since it's ambiguous
139 and unreadable, I would like to ban it.
140
141
142
143 3. USE-conditionals inside ||, ??, ^^ groups
144 --------------------------------------------
145
146 This one is not as horrible as the others mentioned but it seems to have
147 barely any use, unnecessarily complexifies the AST and damages
148 readability. I'm talking about cases like:
149
150 || ( a foo? ( b ) c )
151
152 which is roughly equivalent to:
153
154 foo? ( || ( a b c ) )
155 !foo? ( || ( a c ) )
156
157 The only use I've seen is media-video/mpv:
158
159 || ( cli libmpv ) [...]
160 opengl? ( || ( aqua egl X raspberry-pi !cli? ( libmpv ) ) )
161
162 which is probably completely meaningless since you have to either enable
163 cli or libmpv in the first place.
164
165 I don't have *that* very strong opinion on this but I'd rather ban it
166 and expect people to use more straightforward (= readable
167 and predictable expressions).
168
169
170 Resulting AST
171 =============
172
173 If all three classes I've mentioned were banned, the AST would look
174 like:
175
176 REQUIRED_USE := [<top-expr>...]
177
178 top-expr := <flag> | <use-cond> | <any-of> | <most-one-of> | <exactly-one-of>
179
180 flag := ['!']<flag-name>
181
182 use-cond := ['!']<flag-name>'? (' <top-expr>... ')'
183
184 any-of := '|| (' <any-of-expr>... ')'
185
186 any-of-expr := <flag> | <all-of>
187
188 most-one-of := '??' ( <flag>... )
189
190 exactly-one-of := '^^' ( <flag>... )
191
192 all-of := '(' <flag>... ')'
193
194
195 Note that only USE conditionals are deeply nested now. Of all other
196 groups, || can contain pure flags and/or all-of blocks (which contain
197 only pure flags), and ?? and ^^ contain pure flags only.
198
199 Your thoughts?
200
201
202 [1]:https://projects.gentoo.org/pms/6/pms.html#x1-690007.3
203 [2]:https://projects.gentoo.org/pms/6/pms.html#x1-910008.2.7
204 [3]:https://projects.gentoo.org/pms/6/pms.html#x1-780008.2
205
206 --
207 Best regards,
208 Michał Górny

Attachments

File name MIME type
signature.asc application/pgp-signature

Replies