On śro, 2017-05-31 at 19:39 +0200, Alexis Ballier wrote:
> > >  Again, you *need* to process the constraints in order. '!a?
> > > ( b ) !b? ( a )' is not deterministic when none of a and b are
> > > enabled otherwise.  
> > 
> > You can't rely on any particular order of constraints, especially when
> > eclass stacking comes into play. You could try defining some
> > constraint- sorting algorithm but it's going to be complex and it's
> > usefulness will be limited anyway due to various kinds of grouping.
> 
> 
> Better have some order: If half of the above constraint comes from
> ebuild and the other half comes from eclass, then PM might toggle 'a' or
> 'b' depending on the phase of the moon which is specifically what we're
> trying to avoid.

No, it can't. That's the whole point. The algorithm must be defined so
that it is always predictable independently of order (maybe except
the ordering inside ^^, ||, ??) and independently of how it's nested
(i.e. 'a? ( b? ( c ) )' must give the same result as 'b? ( a? ( c ) )').

If you start relying on stuff like ordering, you're one step from making
stuff suddenly fail or change meaning due to minor changes, like sorting
stuff.

> eclass stacking is not a problem: specify if it's append or prepend and
> be done.

What about multiple inherits with guards? Next thing I know, we end up
putting REQUIRED_USE outside guards (like we have to do with
EXPORT_FUNCTIONS now) because you need a specific order, and guards make
it unpredictable.

> Note that if you want to remove the need for an order, you'll need to
> ensure that all orderings of the constraints give the same result. It's
> not sufficient to "only" check all possible inputs.

That's the matter of the algorithm.

> Also, what happens if we applied all the constraints and obtained some
> useflags setting that still fails REQUIRED_USE check ?

It can't happen. If you can apply all the constraints, then implicitly
REQUIRED_USE is satisfied. If you can't apply all the constraints, then
it just fails. Of course, we want to ultimately avoid that case.

> > The point would be: by definition, the solver should be able to touch
> > *any* USE flag. If it can't, it mostly implies that you can't use
> > the automatic solver, and so the case is irrelevant for checking.
> > Attempting to go beyond that is going to give a lot of complexity
> > and most likely kill the whole idea.
> > 
> > One thing we need to worry about are masks. We need to think about
> > them.
> 
> It makes zero difference for any solver if you replace variables
> (useflags) by 'true' or 'false' constants (masked/forced/user-forced
> useflags). It's even simpler actually. Whether the formula is not
> constantly 'true' (ie REQUIRED_USE is useless) or constantly
> 'false' (ie there's no way to solve it) is equivalent to solving SAT.
> We likely don't want that for repoman running on php.
> 

Well, probably yes. We just need to make sure to apply them correctly
in different contexts, to avoid accidentally skipping some constraints.
I think it would be reasonably to assume that:

a. flags masked/forced on LHS of implications (foo?) are evaluated
in place, i.e. either always require RHS or remove it completely:

  foo? ( bar )    -> with foo forced, bar is always required
                  => we should also force bar

b. flags masked/forced inside ^^, ??, || alter the contents/meaning --
in particular they might replace the whole construct with a single flag
or make it unsolvable:

  ^^ ( foo bar baz ) -> with foo forced, [bar baz] are never allowed
                     => we should mask them

  || ( foo bar baz ) -> with foo forced, the constraint can be skipped

c. flags masked/forced otherwise can't be altered:

  foo? ( bar )    -> with bar forced, we can skip the constraint.
                  -> with bar masked, foo should be masked as well

Does that cover all the contexts?

-- 
Best regards,
Michał Górny

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to