if w.tpSubscripts || w.ctxt != nil {
w.string(subscript(t.id))
}
+ // If the type parameter name is the same as a predeclared object
+ // (say int), point out where it is declared to avoid confusing
+ // error messages. This doesn't need to be super-elegant; we just
+ // need a clear indication that this is not a predeclared name.
+ if w.ctxt == nil && Universe.Lookup(t.obj.name) != nil {
+ w.string(sprintf(nil, false, " /* with %s declared at %s */", t.obj.name, t.obj.Pos()))
+ }
}
default:
if w.tpSubscripts || w.ctxt != nil {
w.string(subscript(t.id))
}
+ // If the type parameter name is the same as a predeclared object
+ // (say int), point out where it is declared to avoid confusing
+ // error messages. This doesn't need to be super-elegant; we just
+ // need a clear indication that this is not a predeclared name.
+ // Note: types2 prints position information here - we can't do
+ // that because we don't have a token.FileSet accessible.
+ if w.ctxt == nil && Universe.Lookup(t.obj.name) != nil {
+ w.string("/* type parameter */")
+ }
}
default:
--- /dev/null
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import (
+ "sort"
+ "strings"
+)
+
+func f[int any](x int) {
+ x = 0 /* ERRORx "cannot use 0.*(as int.*with int declared at|type parameter)" */
+}
+
+// test case from issue
+
+type Set[T comparable] map[T]struct{}
+
+func (s *Set[string]) String() string {
+ keys := make([]string, 0, len(*s))
+ for k := range *s {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys /* ERRORx "cannot use keys.*with string declared at.*|type parameter" */ )
+ return strings /* ERROR "cannot use strings.Join" */ .Join(keys /* ERRORx "cannot use keys.*with string declared at.*|type parameter" */ , ",")
+}