@@ -149,9 +149,19 @@ object Plugins {
149149 type OrderingReq = (Set [Class [_]], Set [Class [_]])
150150
151151 val orderRequirements = MMap [Class [_], OrderingReq ]()
152- val primitivePhases = plan.flatMap(ps => ps.map(_.getClass : Class [_])).toSet
153152
154- def isPrimitive (phase : Class [_]): Boolean = primitivePhases.contains(phase)
153+ // 1. already inserted phases don't need constraints themselves.
154+ // 2. no need to propagate beyond boundary of inserted phases, as the information
155+ // beyond boundary is less useful than the boundary.
156+ // 3. unsatisfiable constraints will still be exposed by the first plugin in a loop
157+ // due to its conflicting `runAfter` and `runBefore` after propagation. The ordering
158+ // of primitive phases (`plan`) are used to check `runAfter` and `runBefore`, thus
159+ // there is no need to propagate the primitive phases.
160+
161+ var insertedPhase = plan.flatMap(ps => ps.map(_.getClass : Class [_])).toSet
162+ def isInserted (phase : Class [_]): Boolean = insertedPhase.contains(phase)
163+
164+ var updatedPlan = plan
155165
156166 def constraintConflict (phase : Phase ): String = {
157167 val (runsAfter, runsBefore) = orderRequirements(phase.getClass)
@@ -176,12 +186,12 @@ object Plugins {
176186 var (runsAfter, runsBefore) = orderRequirements(phase.getClass)
177187
178188 // propagate transitive constraints to related phases
179- runsAfter.filter(! isPrimitive (_)).foreach { phaseClass =>
189+ runsAfter.filter(! isInserted (_)).foreach { phaseClass =>
180190 val (runsAfter1, runsBefore1) = orderRequirements(phaseClass)
181191 orderRequirements.update(phaseClass, (runsAfter1, runsBefore1 + phase.getClass))
182192 }
183193
184- runsBefore.filter(! isPrimitive (_)).foreach { phaseClass =>
194+ runsBefore.filter(! isInserted (_)).foreach { phaseClass =>
185195 val (runsAfter1, runsBefore1) = orderRequirements(phaseClass)
186196 orderRequirements.update(phaseClass, (runsAfter1 + phase.getClass, runsBefore1))
187197 }
@@ -199,7 +209,7 @@ object Plugins {
199209 def propagateRunsBefore (beforePhase : Class [_]): Set [Class [_]] =
200210 if (beforePhase == phase.getClass)
201211 throw new Exception (constraintConflict(phase))
202- else if (primitivePhases.contains (beforePhase))
212+ else if (isInserted (beforePhase))
203213 Set (beforePhase)
204214 else {
205215 val (_, runsBefore) = orderRequirements(beforePhase)
@@ -209,7 +219,7 @@ object Plugins {
209219 def propagateRunsAfter (afterPhase : Class [_]): Set [Class [_]] =
210220 if (afterPhase == phase.getClass)
211221 throw new Exception (constraintConflict(phase))
212- else if (primitivePhases.contains (afterPhase))
222+ else if (isInserted (afterPhase))
213223 Set (afterPhase)
214224 else {
215225 val (runsAfter, _) = orderRequirements(afterPhase)
@@ -224,8 +234,6 @@ object Plugins {
224234 (runsAfter, runsBefore)
225235 }
226236
227- var updatedPlan = plan
228- var insertedPhase = primitivePhases
229237 pluginPhases.sortBy(_.phaseName).foreach { phase =>
230238 var (runsAfter1, runsBefore1) = propagate(phase)
231239
0 commit comments