package solve

import (
	
	
	
	

	
	
)

// topoOrder returns the instances in dependency order: every producer precedes
// the consumers of its outputs. Ties are broken by source position so the order
// is deterministic and independent of how packages and files were read. A cycle
// is reported as a located path.
//
// The selection loop below is O(V²·arity): each emitted node rescans all
// instances and re-checks their dependency sets. That is quadratic, but V is
// bounded by maxInstantiations and tiny for real sets (tens of instances; a
// deepening generic template trips maxTypeDepth long before it manufactures
// thousands of instances), so ordering stays sub-millisecond in practice. Kahn's
// O(V+E) would be premature. The rescan also gives the deterministic
// position-ordered pick and feeds the cycle report for free.
func ( *solver) ( *Plan) ([]*Instance, *diag.Error) {
	 := slices.SortedStableFunc(slices.Values(.instances), func(,  *Instance) int { return diag.CmpPos(.pos, .pos) })

	// deps[in] = the producer instances in must follow.
	 := map[*Instance]map[*Instance]bool{}
	for ,  := range  {
		[] = map[*Instance]bool{}
		for ,  := range .Args[] {
			if .isParam {
				continue
			}
			// A self-edge (a provider consuming a type it produces, directly or
			// via the value/pointer bridge) is a single-node cycle, so it is kept.
			if ,  := .supply.At(.SrcType);  {
				[][] = true
			}
		}
	}

	 := map[*Instance]bool{}
	var  []*Instance
	for len() < len() {
		 := false
		for ,  := range  { // already position-sorted: deterministic pick
			if [] {
				continue
			}
			 := true
			for  := range [] {
				if ![] {
					 = false
					break
				}
			}
			if  {
				[] = true
				 = append(, )
				 = true
				break
			}
		}
		if ! {
			return nil, .cycleError(, , , )
		}
	}
	return , nil
}

// cycleError finds a dependency cycle among the not-yet-emitted instances and
// reports it as a path, naming the type each provider needs from the next.
func ( *solver) ( *Plan,  []*Instance,  map[*Instance]bool,  map[*Instance]map[*Instance]bool) *diag.Error {
	var  []*Instance
	for ,  := range  {
		if ![] {
			 = append(, )
		}
	}
	const (
		 = iota // unvisited
		         // on the current DFS stack
		        // fully explored
	)
	 := map[*Instance]int{}
	var  []*Instance
	var  []*Instance

	var  func( *Instance) bool
	 = func( *Instance) bool {
		[] = 
		 = append(, )
		// deterministic neighbor order
		var  []*Instance
		for  := range [] {
			if ![] {
				 = append(, )
			}
		}
		slices.SortStableFunc(, func(,  *Instance) int { return diag.CmpPos(.pos, .pos) })
		for ,  := range  {
			switch [] {
			case :
				// found a cycle: slice the stack from d onward
				for ,  := range slices.Backward() {
					if  ==  {
						 = append([]*Instance{}, [:]...)
						return true
					}
				}
				return true
			case :
				if () {
					return true
				}
			}
		}
		[] = 
		 = [:len()-1]
		return false
	}

	for ,  := range  {
		if [] ==  {
			if () {
				break
			}
		}
	}

	if len() == 0 {
		// Should be unreachable: no progress implies a cycle exists.
		panic("plumb: ordering stalled without a detectable cycle")
	}
	// Render the cycle as "A needs T1 → B needs T2 → A", naming on each edge the
	// type the provider consumes from the next one round the loop.
	var  []string
	for ,  := range  {
		 := [(+1)%len()]
		if ,  := .edgeType(, , );  != nil {
			 := gotypes.TypeName()
			if  {
				 += " (bridged)"
			}
			 = append(, fmt.Sprintf("%s needs %s", .Prov.Name, ))
		} else {
			 = append(, .Prov.Name)
		}
	}
	 = append(, [0].Prov.Name)
	return diag.Errorf([0].pos, diag.ErrDependencyCycle, "set %q: %s", .name, strings.Join(, " → "))
}

// edgeType returns the type consumer declares as the input that producer supplies
// (the dependency that makes consumer follow producer) and whether that input is
// satisfied through the value/pointer bridge. It reports the consumer's demanded
// type (its InputSlot), not the producer's SrcType, so the diagnostic names the
// type as written in the source; on a bridged edge the two are duals. The type is
// nil if no such edge exists (defensive; cycle edges always have one).
func ( *solver) ( *Plan, ,  *Instance) (types.Type, bool) {
	for ,  := range .Args[] {
		if .isParam {
			continue
		}
		if ,  := .supply.At(.SrcType);  &&  ==  {
			return .Inputs[].typ, .Coerce != CoerceNone
		}
	}
	return nil, false
}