package solve
import (
)
type injectorInput struct {
typ types.Type
pos token.Position
name string
}
func ( *solver) () (*Plan, *diag.Error) {
:= &Plan{
Name: .name,
pos: .setPos(),
Args: map[*Instance][]ArgRef{},
ProviderCount: len(.provs),
}
var gotypes.Set[types.Type]
var gotypes.Map[types.Type, *injectorInput]
for , := range .instances {
:= make([]ArgRef, len(.Inputs))
for , := range .Inputs {
, := .resolveInput(, )
if != nil {
return nil,
}
[] =
if .isParam {
if , := .At(.SrcType); ! {
.Set(.SrcType, &injectorInput{typ: .SrcType, pos: .pos, name: .Name})
} else if diag.CmpPos(.pos, .pos) < 0 {
.pos = .pos
.name = .Name
}
} else {
.Add(.SrcType)
}
}
.Args[] =
}
var []types.Type
for , := range .instances {
for , := range .valueOuts() {
if !.Contains() {
= append(, )
}
}
}
sortTypesByProducer(, &.supply)
.Outputs =
:= make([]*injectorInput, 0, .Len())
for , := range .All {
= append(, )
}
slices.SortFunc(, func(, *injectorInput) int {
return cmp.Or(diag.CmpPos(.pos, .pos), gotypes.CmpType(.typ, .typ))
})
for , := range {
.Inputs = append(.Inputs, Input{Type: .typ, Name: .name})
}
for , := range .instances {
for , := range .Results {
switch .Kind {
case ResultKindCleanup:
.AnyCleanup = true
if .Failable {
.CleanupFailable = true
}
case ResultKindError:
.Fallible = true
}
}
}
.Lifted = .orderedLifted()
if := .checkReachability(); != nil {
return nil,
}
if := .checkReservedAndCollision(); != nil {
return nil,
}
, := .topoOrder()
if != nil {
return nil,
}
.Order =
return , nil
}
func ( *solver) ( *Instance, InputSlot) (ArgRef, *diag.Error) {
:= .typ
if := .checkInputType(, ); != nil {
return ArgRef{},
}
if , := .supply.At(); {
return ArgRef{SrcType: , Coerce: CoerceNone}, nil
}
if , := gotypes.DualType(); {
if , := .supply.At(); {
return ArgRef{SrcType: , Coerce: bridgeDir()}, nil
}
}
return ArgRef{isParam: true, SrcType: }, nil
}
func ( []types.Type, *gotypes.Map[types.Type, *Instance]) {
:= func( types.Type) *Instance {
, := .At()
return
}
slices.SortStableFunc(, func(, types.Type) int {
:= ()
:= ()
if != nil && != nil {
if := diag.CmpPos(.pos, .pos); != 0 {
return
}
}
return gotypes.CmpType(, )
})
}