package emitimport ()// renderInstance renders the value-producing expression for one instance: the// provider call or reference, given a qualifier and the already-coerced argument// expressions in input order. It is the single place provider kinds turn into Go// source: solve decides the wiring, emit renders it.func ( *solve.Instance, *qualifier, []string) string { := .Provswitch .Kind {casediscover.KindFunc:varstrings.Builder .WriteString(.objQual(.Fn))writeTypeArgs(&, , .Targs) .WriteByte('(')writeArgs(&, , .Fn.Type().(*types.Signature).Variadic()) .WriteByte(')')return .String()casediscover.KindMethod:// args[0] is the receiver expression. Variadic-ness is stable under // instantiation, so the origin method signature is authoritative.varstrings.Builder .WriteString(asReceiver([0])) .WriteByte('.') .WriteString(.Fn.Name()) .WriteByte('(')writeArgs(&, [1:], .Fn.Type().(*types.Signature).Variadic()) .WriteByte(')')return .String()casediscover.KindSymbol:return .objQual(.Sym)casediscover.KindConvert: := .typeString(.ConvertTo)ifconvNeedsParens(.ConvertTo) { = "(" + + ")" }returnfmt.Sprintf("%s(%s)", , [0])casediscover.KindField:returnasReceiver([0]) + "." + .Sym.Name()casediscover.KindStruct:// The value result is the declared type, rendered as written; the inputs // carry the exported field names in composite-literal order.varstrings.Builder .WriteString(.typeString(.Results[0].Typ)) .WriteByte('{')for , := range {if > 0 { .WriteString(", ") } .WriteString(.Inputs[].Name) .WriteString(": ") .WriteString() } .WriteByte('}')return .String() }panic(fmt.Sprintf("plumb: unhandled provider kind %d", .Kind))}// asReceiver parenthesizes a selector receiver when it is a value/pointer bridge.// The bridge renders *T → T as "*x" and T → *T as "&x"; used bare as a// receiver, "*x.M()" / "&x.M()" parse as "*(x.M())" / "&(x.M())", so they must// become "(*x).M()" / "(&x).M()". A plain local name is already a primary// expression and binds the selector correctly.func ( string) string {ifstrings.HasPrefix(, "*") || strings.HasPrefix(, "&") {return"(" + + ")" }return}// convNeedsParens reports whether a conversion to t must parenthesize the type so// that T(x) is not mis-parsed. T(x) goes wrong two ways: a leading operator (a// pointer *T reads as a dereference, a receive-only <-chan T as a receive), and a// rendered form ending in a result-less func (func()(x) reparses as func() (x),// its result list swallowing the argument). The latter is reachable through slice,// array, map-value, channel, and pointer tails. gofmt rescues neither: it leaves// *T(x) as a dereference and breaks func()-tailed conversions rather than fixing// them. (It does add parens around a top-level func *with* a result, e.g.// func() int(x) → (func() int)(x), so that one case needs no help here.) Every// other target (named/alias/interface/struct/basic types, and composites not// ending in a bare func) renders unambiguously.func ( types.Type) bool {switch u := .(type) {case *types.Pointer:returntruecase *types.Chan:if .Dir() == types.RecvOnly {returntrue } }returnendsInResultlessFunc()}// endsInResultlessFunc reports whether t's rendered form ends in a result-less// func type, reached directly or through a slice/array/map-value/channel/pointer// element or a func's sole result. (A two-or-more result list renders in// parentheses, which closes the type, so it does not end in a bare func.) A named// or alias type renders as its name, so it is opaque and stops the recursion.func ( types.Type) bool {switch u := .(type) {case *types.Signature:switch .Results().Len() {case0:returntruecase1:return (.Results().At(0).Type())default:returnfalse }case *types.Slice:return (.Elem())case *types.Array:return (.Elem())case *types.Map:return (.Elem())case *types.Chan:return (.Elem())case *types.Pointer:return (.Elem()) }returnfalse}func ( *strings.Builder, []string, bool) {for , := range {if > 0 { .WriteString(", ") } .WriteString()if && == len()-1 { .WriteString("...") } }}func ( *strings.Builder, *qualifier, []types.Type) {iflen() == 0 {return } .WriteByte('[')for , := range {if > 0 { .WriteString(", ") } .WriteString(.typeString()) } .WriteByte(']')}
The pages are generated with Goldsv0.8.4. (GOOS=linux GOARCH=amd64)