Consider: https://go.dev/play/p/SiV_jaPuzNr Re-Instantiation of the instantiated type of x in the code works unexpectedly. Re-Instantiation of the instantiated type of f in the code fails as expected.

This seems inconsistent. Either we permit both or neither.

@findleyr for input

Comment From: findleyr

This is just a bug: there are no type params to substitute in the double-instantiated instance. The underlying is the same as the first instance. https://go.dev/play/p/6WDvAzt01tY

It seems we are just missing a check that there are no type arguments.

Comment From: KirtanSoni

May I propose a PR or a Plan on this?

Comment From: obeyda

Hi, It looks like the double instantiation check was removed in CL 333589 when the instantiation logic was moved from subst.go to instantiate.go.

Current state: https://github.com/golang/go/blob/1763ee199d33d2592332a29cfc3da7811718a4fd/src/cmd/compile/internal/types2/instantiate.go#L128-L131 I suggest to fix this by reintroducing the check in instantiate.go. For example:

 case *Named:
+    // Verify type parameter count for named types
+    tparams := orig.TypeParams()
+    if !check.validateTArgLen(pos, orig.obj.Name(), tparams.Len(), len(targs)) {
+        return Typ[Invalid]
+    }
+    if tparams.Len() == 0 {
+        // No type parameters to substitute (orig is not generic or already instantiated)
+        return orig  // nothing to do
+    }
     res = check.newNamedInstance(pos, orig, targs, expanding) // substituted lazily

This should restore the original behavior and prevent double instantiation. Happy to work on a CL if this approach looks acceptable.

Comment From: gopherbot

Change https://go.dev/cl/666115 mentions this issue: go/types, types2: add missing generic type test to Checker.Instantiate

Comment From: gopherbot

Change https://go.dev/cl/666435 mentions this issue: go/types, types2: add tests for duplicate instantiation