From 9e63fccb51e5425dd20d0750d573ff51ce6525bf Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Wed, 30 Apr 2008 13:20:22 +0000 Subject: [PATCH] - add obsoleteusesprovides and implicitobsoleteusesprovides solver flags - speed up solving by not recreating the watch chains every time some rule is enabled/disabled. To do this, the "disabled" flag had to be moved from w1 to d. - fix bug that broke rule disabling when "forceResolve" was true - fix bug in update rule calculation --- src/solver.c | 174 +++++++++++++++++++++++++++++++++--------------------- src/solver.h | 9 ++- src/solverdebug.c | 28 +++++---- 3 files changed, 131 insertions(+), 80 deletions(-) diff --git a/src/solver.c b/src/solver.c index 05a586f..ea1c686 100644 --- a/src/solver.c +++ b/src/solver.c @@ -417,16 +417,15 @@ addrule(Solver *solv, Id p, Id d) static inline void disablerule(Solver *solv, Rule *r) { - r->w1 = 0; + if (r->d >= 0) + r->d = -r->d - 1; } static inline void enablerule(Solver *solv, Rule *r) { - if (r->d == 0 || r->w2 != r->p) - r->w1 = r->p; - else - r->w1 = solv->pool->whatprovidesdata[r->d]; + if (r->d < 0) + r->d = -r->d - 1; } @@ -469,7 +468,7 @@ enableproblem(Solver *solv, Id v) { /* do not enable feature rule if update rule is enabled */ r = solv->rules + v - (solv->installed->end - solv->installed->start); - if (r->w1) + if (r->d >= 0) return; } enablerule(solv, solv->rules + v); @@ -513,7 +512,7 @@ makeruledecisions(Solver *solv) /* nowadays they can be weak, so start with rule 1 */ for (ri = 1, r = solv->rules + ri; ri < solv->nrules; ri++, r++) { - if (!r->w1 || r->w2) /* disabled or no assertion */ + if (r->d < 0 || !r->p || r->w2) /* disabled, dummy or no assertion */ continue; /* do weak rules in phase 2 */ if (ri < solv->learntrules && MAPTST(&solv->weakrulemap, ri)) @@ -602,7 +601,7 @@ makeruledecisions(Solver *solv) /* push all of our rules asserting this literal on the problem stack */ for (i = solv->jobrules, rr = solv->rules + i; i < solv->nrules; i++, rr++) { - if (!rr->w1 || rr->w2) + if (rr->d < 0 || rr->w2) continue; if (rr->p != vv && rr->p != -vv) continue; @@ -634,7 +633,7 @@ makeruledecisions(Solver *solv) /* phase 2: now do the weak assertions */ for (ri = 1, r = solv->rules + ri; ri < solv->learntrules; ri++, r++) { - if (!r->w1 || r->w2) /* disabled or no assertion */ + if (r->d < 0 || r->w2) /* disabled or no assertion */ continue; if (!MAPTST(&solv->weakrulemap, ri)) continue; @@ -687,11 +686,11 @@ enabledisablelearntrules(Solver *solv) while ((why = *whyp++) != 0) { assert(why > 0 && why < i); - if (!solv->rules[why].w1) + if (solv->rules[why].d < 0) break; } /* why != 0: we found a disabled rule, disable the learnt rule */ - if (why && r->w1) + if (why && r->d >= 0) { IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) { @@ -700,7 +699,7 @@ enabledisablelearntrules(Solver *solv) } disablerule(solv, r); } - else if (!why && !r->w1) + else if (!why && r->d < 0) { IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) { @@ -720,7 +719,7 @@ enableweakrules(Solver *solv) for (i = solv->jobrules, r = solv->rules + i; i < solv->learntrules; i++, r++) { - if (r->w1) + if (r->d >= 0) continue; if (!MAPTST(&solv->weakrulemap, i)) continue; @@ -766,7 +765,7 @@ disableupdaterules(Solver *solv, Queue *job, int jobidx) for (i = solv->jobrules; i < solv->updaterules; i++) { r = solv->rules + i; - if (!r->w1) /* disabled? */ + if (r->d < 0) /* disabled? */ continue; j = solv->ruletojob.elements[i - solv->jobrules]; if (j == lastjob) @@ -813,9 +812,6 @@ disableupdaterules(Solver *solv, Queue *job, int jobidx) } /* fixup update rule status */ - if (solv->allowuninstall) - return; /* no update rules at all */ - if (jobidx != -1) { /* we just disabled job #jobidx. enable all update rules @@ -835,7 +831,7 @@ disableupdaterules(Solver *solv, Queue *job, int jobidx) if (MAPTST(&solv->noupdate, p - installed->start)) continue; r = solv->rules + solv->updaterules + (p - installed->start); - if (r->w1) + if (r->d >= 0) continue; enablerule(solv, r); IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) @@ -852,7 +848,7 @@ disableupdaterules(Solver *solv, Queue *job, int jobidx) if (MAPTST(&solv->noupdate, what - installed->start)) break; r = solv->rules + solv->updaterules + (what - installed->start); - if (r->w1) + if (r->d >= 0) break; enablerule(solv, r); IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) @@ -878,7 +874,7 @@ disableupdaterules(Solver *solv, Queue *job, int jobidx) if (MAPTST(&solv->noupdate, p - installed->start)) continue; r = solv->rules + solv->updaterules + (p - installed->start); - if (r->w1) + if (r->d >= 0) continue; enablerule(solv, r); IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) @@ -897,10 +893,10 @@ disableupdaterules(Solver *solv, Queue *job, int jobidx) for (i = 0; i < installed->nsolvables; i++) { r = solv->rules + solv->updaterules + i; - if (r->w1 && MAPTST(&solv->noupdate, i)) + if (r->d >= 0 && MAPTST(&solv->noupdate, i)) disablerule(solv, r); /* was enabled, need to disable */ r = solv->rules + solv->featurerules + i; - if (r->w1 && MAPTST(&solv->noupdate, i)) + if (r->d >= 0 && MAPTST(&solv->noupdate, i)) disablerule(solv, r); /* was enabled, need to disable */ } } @@ -1122,13 +1118,18 @@ addrpmrulesforsolvable(Solver *solv, Solvable *s, Map *m) while ((obs = *obsp++) != 0) { FOR_PROVIDES(p, pp, obs) - addrule(solv, -n, -p); + { + if (!solv->obsoleteusesprovides && s->name != pool->solvables[p].name) + continue; + addrule(solv, -n, -p); + } } } FOR_PROVIDES(p, pp, s->name) { - if (s->name == pool->solvables[p].name) - addrule(solv, -n, -p); + if (!solv->implicitobsoleteusesprovides && s->name != pool->solvables[p].name) + continue; + addrule(solv, -n, -p); } } @@ -1287,8 +1288,7 @@ makewatches(Solver *solv) for (i = 1, r = solv->rules + 1; i < solv->nrules; i++, r++) #endif { - if (!r->w1 /* rule is disabled */ - || !r->w2) /* rule is assertion */ + if (!r->w2) /* assertions do not need watches */ continue; /* see addwatches_rule(solv, r) */ @@ -1358,6 +1358,15 @@ propagate(Solver *solv, int level) for (rp = watches + pkg; *rp; rp = nrp) { r = solv->rules + *rp; + if (r->d < 0) + { + /* rule is disabled */ + if (pkg == r->w1) + nrp = &r->n1; + else + nrp = &r->n2; + continue; + } IF_POOLDEBUG (SAT_DEBUG_PROPAGATE) { @@ -1461,7 +1470,7 @@ analyze(Solver *solv, int level, Rule *c, int *pr, int *dr, int *whyp) Queue r; int rlevel = 1; Map seen; /* global? */ - Id v, vv, *dp, why; + Id d, v, vv, *dp, why; int l, i, idx; int num = 0, l1num = 0; int learnt_why = solv->learnt_pool.count; @@ -1477,13 +1486,14 @@ analyze(Solver *solv, int level, Rule *c, int *pr, int *dr, int *whyp) IF_POOLDEBUG (SAT_DEBUG_ANALYZE) solver_printruleclass(solv, SAT_DEBUG_ANALYZE, c); queue_push(&solv->learnt_pool, c - solv->rules); - dp = c->d ? pool->whatprovidesdata + c->d : 0; + d = c->d < 0 ? -c->d - 1 : c->d; + dp = d ? pool->whatprovidesdata + d : 0; /* go through all literals of the rule */ for (i = -1; ; i++) { if (i == -1) v = c->p; - else if (c->d == 0) + else if (d == 0) v = i ? 0 : c->w2; else v = *dp++; @@ -1599,9 +1609,6 @@ reset_solver(Solver *solv) /* redo all job/update decisions */ makeruledecisions(solv); POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "decisions so far: %d\n", solv->decisionq.count); - - /* recreate watch chains */ - makewatches(solv); } @@ -1660,7 +1667,7 @@ analyze_unsolvable(Solver *solv, Rule *cr, int disablerules) Pool *pool = solv->pool; Rule *r; Map seen; /* global to speed things up? */ - Id v, vv, *dp, why; + Id d, v, vv, *dp, why; int l, i, idx; Id *decisionmap = solv->decisionmap; int oldproblemcount; @@ -1682,12 +1689,13 @@ analyze_unsolvable(Solver *solv, Rule *cr, int disablerules) queue_push(&solv->learnt_pool, r - solv->rules); lastweak = 0; analyze_unsolvable_rule(solv, r, &lastweak); - dp = r->d ? pool->whatprovidesdata + r->d : 0; + d = r->d < 0 ? -r->d - 1 : r->d; + dp = d ? pool->whatprovidesdata + d : 0; for (i = -1; ; i++) { if (i == -1) v = r->p; - else if (r->d == 0) + else if (d == 0) v = i ? 0 : r->w2; else v = *dp++; @@ -1712,12 +1720,13 @@ analyze_unsolvable(Solver *solv, Rule *cr, int disablerules) queue_push(&solv->learnt_pool, why); r = solv->rules + why; analyze_unsolvable_rule(solv, r, &lastweak); - dp = r->d ? pool->whatprovidesdata + r->d : 0; + d = r->d < 0 ? -r->d - 1 : r->d; + dp = d ? pool->whatprovidesdata + d : 0; for (i = -1; ; i++) { if (i == -1) v = r->p; - else if (r->d == 0) + else if (d == 0) v = i ? 0 : r->w2; else v = *dp++; @@ -1810,11 +1819,12 @@ static inline void watch2onhighest(Solver *solv, Rule *r) { int l, wl = 0; - Id v, *dp; + Id d, v, *dp; - if (!r->d) + d = r->d < 0 ? -r->d - 1 : r->d; + if (!d) return; /* binary rule, both watches are set */ - dp = solv->pool->whatprovidesdata + r->d; + dp = solv->pool->whatprovidesdata + d; while ((v = *dp++) != 0) { l = solv->decisionmap[v < 0 ? -v : v]; @@ -2125,6 +2135,7 @@ run_solver(Solver *solv, int disablerules, int doweak) for (i = solv->installed->start, r = solv->rules + solv->updaterules; i < solv->installed->end; i++, r++) { Rule *rr; + Id d; s = pool->solvables + i; if (s->repo != solv->installed) continue; @@ -2135,11 +2146,12 @@ run_solver(Solver *solv, int disablerules, int doweak) continue; queue_empty(&dq); rr = r; - if (!rr->w1) + if (rr->d < 0) /* disabled ? */ rr += solv->installed->end - solv->installed->start; if (!rr->p) /* identical to update rule? */ rr = r; - if (rr->d == 0) + d = rr->d < 0 ? -rr->d - 1 : rr->d; + if (d == 0) { if (!rr->w2 || solv->decisionmap[rr->w2] > 0) continue; @@ -2148,7 +2160,7 @@ run_solver(Solver *solv, int disablerules, int doweak) } else { - dp = pool->whatprovidesdata + rr->d; + dp = pool->whatprovidesdata + d; while ((p = *dp++) != 0) { if (solv->decisionmap[p] > 0) @@ -2191,7 +2203,7 @@ run_solver(Solver *solv, int disablerules, int doweak) if (i == solv->nrules) i = 1; r = solv->rules + i; - if (!r->w1) /* ignore disabled rules */ + if (r->d < 0) /* ignore disabled rules */ continue; queue_empty(&dq); if (r->d == 0) @@ -2617,7 +2629,7 @@ problems_to_solutions(Solver *solv, Queue *job) else { /* update rule, find replacement package */ - Id p, rp = 0; + Id p, d, *dp, rp = 0; Rule *rr; p = solv->installed->start + (why - solv->updaterules); if (solv->decisionmap[p] > 0) @@ -2627,15 +2639,15 @@ problems_to_solutions(Solver *solv, Queue *job) rr = solv->rules + why; if (rr->w2) { - if (!rr->d) + d = rr->d < 0 ? -rr->d - 1 : rr->d; + if (!d) { if (solv->decisionmap[rr->w2] > 0 && pool->solvables[rr->w2].repo != solv->installed) rp = rr->w2; } else { - Id *dp = pool->whatprovidesdata + rr->d; - for (; *dp; dp++) + for (dp = pool->whatprovidesdata + d; *dp; dp++) { if (solv->decisionmap[*dp] > 0 && pool->solvables[*dp].repo != solv->installed) { @@ -2730,7 +2742,7 @@ solver_problemruleinfo(Solver *solv, Queue *job, Id rid, Id *depp, Id *sourcep, Rule *r; Solvable *s; int dontfix = 0; - Id p, *pp, req, *reqp, con, *conp, obs, *obsp, *dp; + Id p, d, *pp, req, *reqp, con, *conp, obs, *obsp, *dp; assert(rid > 0); if (rid >= solv->updaterules) @@ -2748,13 +2760,15 @@ solver_problemruleinfo(Solver *solv, Queue *job, Id rid, Id *depp, Id *sourcep, *depp = job->elements[p + 1]; *sourcep = p; *targetp = job->elements[p]; - if (r->d == 0 && r->w2 == 0 && r->p == -SYSTEMSOLVABLE && job->elements[p] != SOLVER_INSTALL_SOLVABLE_ONE_OF) + d = r->d < 0 ? -r->d - 1 : r->d; + if (d == 0 && r->w2 == 0 && r->p == -SYSTEMSOLVABLE && job->elements[p] != SOLVER_INSTALL_SOLVABLE_ONE_OF) return SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP; return SOLVER_PROBLEM_JOB_RULE; } r = solv->rules + rid; assert(r->p < 0); - if (r->d == 0 && r->w2 == 0) + d = r->d < 0 ? -r->d - 1 : r->d; + if (d == 0 && r->w2 == 0) { /* a rpm rule assertion */ s = pool->solvables - r->p; @@ -2802,7 +2816,7 @@ solver_problemruleinfo(Solver *solv, Queue *job, Id rid, Id *depp, Id *sourcep, s = pool->solvables - r->p; if (installed && !solv->fixsystem && s->repo == installed) dontfix = 1; - if (r->d == 0 && r->w2 < 0) + if (d == 0 && r->w2 < 0) { /* a package conflict */ Solvable *s2 = pool->solvables - r->w2; @@ -2868,6 +2882,8 @@ solver_problemruleinfo(Solver *solv, Queue *job, Id rid, Id *depp, Id *sourcep, { if (p != -r->w2) continue; + if (!solv->obsoleteusesprovides && s->name != pool->solvables[p].name) + continue; *depp = obs; *sourcep = -r->p; *targetp = p; @@ -2884,6 +2900,8 @@ solver_problemruleinfo(Solver *solv, Queue *job, Id rid, Id *depp, Id *sourcep, { if (p != -r->p) continue; + if (!solv->obsoleteusesprovides && s2->name != pool->solvables[p].name) + continue; *depp = obs; *sourcep = -r->w2; *targetp = p; @@ -2891,6 +2909,30 @@ solver_problemruleinfo(Solver *solv, Queue *job, Id rid, Id *depp, Id *sourcep, } } } + if (solv->implicitobsoleteusesprovides && (!installed || s->repo != installed)) + { + FOR_PROVIDES(p, pp, s->name) + { + if (p != -r->w2) + continue; + *depp = s->name; + *sourcep = -r->p; + *targetp = p; + return SOLVER_PROBLEM_PACKAGE_OBSOLETES; + } + } + if (solv->implicitobsoleteusesprovides && (!installed || s2->repo != installed)) + { + FOR_PROVIDES(p, pp, s2->name) + { + if (p != -r->p) + continue; + *depp = s2->name; + *sourcep = -r->w2; + *targetp = p; + return SOLVER_PROBLEM_PACKAGE_OBSOLETES; + } + } /* all cases checked, can't happen */ assert(0); } @@ -2902,12 +2944,12 @@ solver_problemruleinfo(Solver *solv, Queue *job, Id rid, Id *depp, Id *sourcep, if (req == SOLVABLE_PREREQMARKER) continue; dp = pool_whatprovides(pool, req); - if (r->d == 0) + if (d == 0) { if (*dp == r->w2 && dp[1] == 0) break; } - else if (dp - pool->whatprovidesdata == r->d) + else if (dp - pool->whatprovidesdata == d) break; } assert(req); @@ -2920,7 +2962,7 @@ solver_problemruleinfo(Solver *solv, Queue *job, Id rid, Id *depp, Id *sourcep, static void findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp, Id *jobrp) { - Id rid; + Id rid, d; Id lreqr, lconr, lsysr, ljobr; Rule *r; int reqassert = 0; @@ -2944,14 +2986,15 @@ findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp, else { r = solv->rules + rid; - if (!r->d && r->w2 < 0) + d = r->d < 0 ? -r->d - 1 : r->d; + if (!d && r->w2 < 0) { if (!*conrp) *conrp = rid; } else { - if (r->d == 0 && r->w2 == 0 && !reqassert) + if (!d && r->w2 == 0 && !reqassert) { /* prefer assertions (XXX: bad idea?) */ *reqrp = rid; @@ -3025,8 +3068,6 @@ create_obsolete_index(Solver *solv) for (i = 1; i < pool->nsolvables; i++) { s = pool->solvables + i; - if (s->repo == installed) - continue; if (!s->obsoletes) continue; if (!pool_installable(pool, s)) @@ -3054,8 +3095,6 @@ create_obsolete_index(Solver *solv) for (i = pool->nsolvables - 1; i > 0; i--) { s = pool->solvables + i; - if (s->repo == installed) - continue; if (!s->obsoletes) continue; if (!pool_installable(pool, s)) @@ -3097,7 +3136,7 @@ removedisabledconflicts(Solver *solv, Queue *removed) why = solv->decisionq_why.elements[i]; assert(why > 0); r = solv->rules + why; - if (!r->w1 && decisionmap[-p]) + if (r->d < 0 && decisionmap[-p]) { /* rule is now disabled, remove from decisionmap */ POOL_DEBUG(SAT_DEBUG_STATS, "removing conflict for package %s[%d]\n", solvable2str(pool, pool->solvables - p), -p); @@ -3118,7 +3157,7 @@ removedisabledconflicts(Solver *solv, Queue *removed) i = 1; r = solv->rules + i; } - if (!r->w1) + if (r->d < 0) continue; if (!r->w2) { @@ -3181,7 +3220,7 @@ weaken_solvable_deps(Solver *solv, Id p) { if (r->p != -p) continue; - if (r->d == 0 && r->w2 < 0) + if ((r->d == 0 || r->d == -1) && r->w2 < 0) continue; /* conflict */ queue_push(&solv->weakruleq, i); } @@ -3527,12 +3566,13 @@ solver_solve(Solver *solv, Queue *job) addupdaterule(solv, s, 1); r = solv->rules + solv->nrules - 1; sr = r - (installed->end - installed->start); - disablerule(solv, r); if (!unifyrules_sortcmp(r, sr)) { /* identical rule, kill feature rule */ memset(r, 0, sizeof(*r)); } + if (r->p) + disablerule(solv, r); if (r->p && solv->allowuninstall) queue_push(&solv->weakruleq, solv->nrules - 1); } @@ -3574,7 +3614,7 @@ solver_solve(Solver *solv, Queue *job) /* disable all erase jobs (including weak "keep uninstalled" rules) */ for (i = solv->jobrules, r = solv->rules + i; i < solv->updaterules; i++, r++) { - if (!r->w1) + if (r->d < 0) /* disabled ? */ continue; if (r->p > 0) /* install job? */ continue; diff --git a/src/solver.h b/src/solver.h index 79b4906..d321e63 100644 --- a/src/solver.h +++ b/src/solver.h @@ -51,8 +51,8 @@ typedef struct rule { Id p; /* first literal in rule */ Id d; /* Id offset into 'list of providers terminated by 0' as used by whatprovides; pool->whatprovides + d */ /* in case of binary rules, d == 0, w1 == p, w2 == other literal */ + /* in case of disabled rules: ~d, aka -d - 1 */ Id w1, w2; /* watches, literals not-yet-decided */ - /* if !w1, disabled */ /* if !w2, assertion, not rule */ Id n1, n2; /* next rules in linked list, corresponding to w1,w2 */ } Rule; @@ -127,6 +127,8 @@ typedef struct solver { int updatesystem; /* distupgrade */ int allowvirtualconflicts; /* false: conflicts on package name, true: conflicts on package provides */ int allowselfconflicts; /* true: packages wich conflict with itself are installable */ + int obsoleteusesprovides; /* true: obsoletes are matched against provides, not names */ + int implicitobsoleteusesprovides; /* true: implicit obsoletes due to same name are matched against provides, not names */ int noupdateprovide; /* true: update packages needs not to provide old package */ int dosplitprovides; /* true: consider legacy split provides */ int dontinstallrecommended; /* true: do not install recommended packages */ @@ -303,6 +305,11 @@ solver_create_state_maps(Solver *solv, Map *installedmap, Map *conflictsmap) pool_create_state_maps(solv->pool, &solv->decisionq, installedmap, conflictsmap); } +#define FOR_RULELITERALS(l, dp, r) \ + for (l = r->d < 0 ? -r->d - 1 : r->d, \ + dp = !l ? &r->w2 : pool->whatprovidesdata + l, \ + l = r->p; l; l = (dp != &r->w2 + 1 ? *dp++ : 0)) + #ifdef __cplusplus } #endif diff --git a/src/solverdebug.c b/src/solverdebug.c index 9ff2023..993bc23 100644 --- a/src/solverdebug.c +++ b/src/solverdebug.c @@ -61,14 +61,15 @@ solver_create_decisions_obsoletesmap(Solver *solv) if (s->repo == installed) /* obsoletes don't count for already installed packages */ continue; FOR_PROVIDES(p, pp, s->name) - if (s->name == pool->solvables[p].name) - { - if (pool->solvables[p].repo == installed && !obsoletesmap[p]) - { - obsoletesmap[p] = n; - obsoletesmap[n]++; - } - } + { + if (!solv->implicitobsoleteusesprovides && s->name != pool->solvables[p].name) + continue; + if (pool->solvables[p].repo == installed && !obsoletesmap[p]) + { + obsoletesmap[p] = n; + obsoletesmap[n]++; + } + } } for (i = 0; i < solv->decisionq.count; i++) { @@ -89,6 +90,8 @@ solver_create_decisions_obsoletesmap(Solver *solv) while ((obs = *obsp++) != 0) FOR_PROVIDES(p, pp, obs) { + if (!solv->obsoleteusesprovides && s->name != pool->solvables[p].name) + continue; if (pool->solvables[p].repo == installed && !obsoletesmap[p]) { obsoletesmap[p] = n; @@ -139,21 +142,22 @@ solver_printrule(Solver *solv, int type, Rule *r) { Pool *pool = solv->pool; int i; - Id v; + Id d, v; if (r >= solv->rules && r < solv->rules + solv->nrules) /* r is a solver rule */ POOL_DEBUG(type, "Rule #%d:", (int)(r - solv->rules)); else POOL_DEBUG(type, "Rule:"); /* r is any rule */ - if (r && r->w1 == 0) + if (r && r->d < 0) POOL_DEBUG(type, " (disabled)"); POOL_DEBUG(type, "\n"); + d = r->d < 0 ? -r->d - 1 : r->d; for (i = 0; ; i++) { if (i == 0) /* print direct literal */ v = r->p; - else if (r->d == ID_NULL) + else if (!d) { if (i == 2) break; @@ -162,7 +166,7 @@ solver_printrule(Solver *solv, int type, Rule *r) } else /* every other which is in d */ - v = solv->pool->whatprovidesdata[r->d + i - 1]; + v = solv->pool->whatprovidesdata[d + i - 1]; if (v == ID_NULL) break; solver_printruleelement(solv, type, r, v); -- 2.7.4