golang/go · error

%s does not %s %s (%s)

Error message

%s does not %s %s (%s)

What it means

Produced by types2 Checker.verify (src/cmd/compile/internal/types2/instantiate.go:228) when instantiating a generic type/function and a type argument fails to satisfy its type-parameter bound. The actual message text is assembled in Checker.implements via check.sprintf("%s does not %s %s (%s)", V, verb, T, detail); verify wraps the cause string in errors.New. The verb is 'satisfy' for constraints or 'implement' for interfaces, and detail explains the specific mismatch (e.g. 'X is not an interface', or a missing method).

Source

Thrown at src/cmd/compile/internal/types2/instantiate.go:228

	}

	panic(fmt.Sprintf("%v: %s", pos, msg))
}

// check may be nil; pos is used only if check is non-nil.
func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type, ctxt *Context) (int, error) {
	smap := makeSubstMap(tparams, targs)
	for i, tpar := range tparams {
		// Ensure that we have a (possibly implicit) interface as type bound (go.dev/issue/51048).
		tpar.iface()
		// The type parameter bound is parameterized with the same type parameters
		// as the instantiated type; before we can use it for bounds checking we
		// need to instantiate it with the type arguments with which we instantiated
		// the parameterized type.
		bound := check.subst(pos, tpar.bound, smap, nil, ctxt)
		var cause string
		if !check.implements(targs[i], bound, true, &cause) {
			return i, errors.New(cause)
		}
	}
	return -1, nil
}

// implements checks if V implements T. The receiver may be nil if implements
// is called through an exported API call such as AssignableTo. If constraint
// is set, T is a type constraint.
//
// If the provided cause is non-nil, it may be set to an error string
// explaining why V does not implement (or satisfy, for constraints) T.
func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool {
	Vu := V.Underlying()
	Tu := T.Underlying()
	if !isValid(Vu) || !isValid(Tu) {
		return true // avoid follow-on errors
	}
	if p, _ := Vu.(*Pointer); p != nil && !isValid(p.base.Underlying()) {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Read the parenthesized detail to identify the missing method or the non-interface bound, then satisfy it on the type argument.
  2. If the argument is correct, relax/fix the constraint (e.g. add the method to an embedded interface, or use constraints.Ordered / comparable correctly).
  3. For comparable constraints, switch to a comparable type argument or wrap the value.
  4. Re-check the generic signature against the call site after any refactor of the constraint.

Example fix

// before
package main
import "fmt"
type Stringer[T any] interface{ String() string }
func Print[T fmt.Stringer](v T) { fmt.Println(v.String()) }
func main() { Print(42) } // int has no String()
// after
type MyInt int
func (m MyInt) String() string { return fmt.Sprint(int(m)) }
func main() { Print(MyInt(42)) }
Defensive patterns

Strategy: validation

Validate before calling

// Use types2 to pre-check that a type argument satisfies a generic constraint
// before committing to the instantiation at scale.
// (Conceptual; in real code, rely on the compiler error and adjust the type/constraint.)
func satisfiesConstraint(typeArg, constraintExpr string) bool {
    // pseudo: invoke go/types Instantiate + Check in a test harness
    return true // placeholder
}

Type guard

// Narrow a type argument to a method-bearing constraint at compile time.
type Stringer interface { String() string }
func assertStringer[T any](v T) Stringer {
    s, ok := any(v).(Stringer)
    if !ok { panic("type argument does not satisfy fmt.Stringer constraint") }
    return s
}

Prevention

When it happens

Trigger: Instantiating a generic type or function with a concrete type argument that does not meet its constraint: either the bound is not an interface at all, or the type lacks a required method, or the type is not in the constraint's type set. Examples: type T[P fmt.Stringer] instantiated with T[int]; type Set[T comparable] instantiated with Set[[]byte].

Common situations: Passing a non-comparable type to a comparable-constrained generic (slices, maps); passing a struct without a required method to a method-constrained generic; a constraint that was narrowed and old call sites no longer fit; cross-package generic API misuse.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/c42833281f5fd2d2. Report an issue: GitHub.