What version of Go are you using (go version
)?
$ go version go version go1.19.1 darwin/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/Users/Will/Library/Caches/go-build" GOENV="/Users/Will/Library/Application Support/go/env" GOEXE="" GOEXPERIMENT="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="darwin" GOINSECURE="" GOMODCACHE="/Users/Will/Developer/go/pkg/mod" GONOPROXY="" GONOSUMDB="" GOOS="darwin" GOPATH="/Users/Will/Developer/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/Cellar/go/1.19.1/libexec" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/Cellar/go/1.19.1/libexec/pkg/tool/darwin_amd64" GOVCS="" GOVERSION="go1.19.1" GCCGO="gccgo" GOAMD64="v1" AR="ar" CC="clang" CXX="clang++" CGO_ENABLED="1" GOMOD="/Users/Will/Developer/ebnf/go.mod" GOWORK="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/bx/qk0phsxd265fqj512dnnpg080000gn/T/go-build1943356326=/tmp/go-build -gno-record-gcc-switches -fno-common" GOROOT/bin/go version: go version go1.19.1 darwin/amd64 GOROOT/bin/go tool compile -V: compile version go1.19.1 uname -v: Darwin Kernel Version 21.6.0: Mon Aug 22 20:17:10 PDT 2022; root:xnu-8020.140.49~2/RELEASE_X86_64 ProductName: macOS ProductVersion: 12.6 BuildVersion: 21G115 lldb --version: lldb-1400.0.30.3 Apple Swift version 5.7 (swiftlang-5.7.0.127.4 clang-1400.0.29.50)
What did you do?
// FirstFollowConflictError is a first/follow LL(1) grammar parse conflict.
type FirstFollowConflictError struct {
Nonterminal string
// An [Identifier] or [Literal]
Terminal any // an [Identifier] or [Literal]
}
$ go doc FirstFollowConflictError
What did you expect to see?
package ebnf // import "."
type FirstFollowConflictError struct {
Nonterminal string
// An Identifier or Literal
Terminal any // an Identifier or Literal
}
FirstFollowConflictError is a first/follow LL(1) grammar parse conflict.
What did you see instead?
package ebnf // import "."
type FirstFollowConflictError struct {
Nonterminal string
// An [Identifier] or [Literal]
Terminal any // an [Identifier] or [Literal]
}
FirstFollowConflictError is a first/follow LL(1) grammar parse conflict.
Note the square brackets around Identifier and Literal above and to the side of the Terminal field. They aren't being parsed and rendered as doc links. The brackets disappear if put above the type declaration, as expected.
Comment From: seankhliao
what are Identifier
and Literal
?
Comment From: willfaught
Struct types in package scope.
package ebnf // import "."
type Identifier struct {
Text string
}
type Literal struct {
Text string
}
Comment From: willfaught
See https://pkg.go.dev/github.com/willfaught/ebnf@v0.4.1#FirstFollowConflictError for the full context, although the brackets are omitted there since it doesn't work.
Comment From: cagedmantis
cc @griesemer
Comment From: ianlancetaylor
See also #59728.
Comment From: Z3NTL3
experiencing something similar can someone have a look at #67473
Comment From: mvdan
Just ran into this myself too; pretty unfortunate as I've come to rely on links pretty heavily for the sake of more information-dense Go documentation.
Comment From: aclements
FWIW, we have a lot of "links" in struct field docs in the Go tree itself that are affected by this. Even, ironically, in the go/doc/comment package!
My search is a bit rough, but it found approximately 83 instances at tip:
$ find -name "*.go" -exec gawk '/^type .*\{/ {t=1} /^}/ {t=0} t&&/[/][/].*\s\[[a-zA-Z]([a-zA-Z0-9_.])*\]/ {print FILENAME ":" FNR ": " $0}' '{}' ';'
./debug/elf/file.go:216: // Use the methods of the [VersionIndex] type to access it. ./builtin/builtin.go:212: // arguments of [cmp.Ordered] types. There must be at least one argument. ./builtin/builtin.go:218: // arguments of [cmp.Ordered] types. There must be at least one argument. ./builtin/builtin.go:290: // a nil argument. See [panic] for details. ./database/sql/driver/driver.go:418: // or shouldn't be handled specially, [DefaultParameterConverter] ./cmd/compile/internal/noder/reader.go:189: // X[string]. [int] and [string] are explicit type arguments for F ./cmd/compile/internal/noder/reader.go:190: // and X, respectively; but [int] is also the implicit type ./cmd/compile/internal/types2/api.go:239: // expression F(int(1)) to the inferred type arguments [int], and resulting ./cmd/compile/internal/types2/object.go:36: // Use [ObjectString] to control how package names are formatted in the string. ./cmd/go/internal/load/printer.go:21: // expected by [fmt.Printf]. ./cmd/go/internal/modfetch/proxy.go:189: redactedBase string // The base module proxy URL in [url.URL.Redacted] form. ./cmd/go/internal/work/exec.go:1119: ID string // package ID (example: "fmt [fmt.test]") ./cmd/internal/obj/x86/evex.go:16: b1 byte // [W1mmLLpp] ./cmd/internal/obj/x86/evex.go:17: b2 byte // [NNNbbZRS] ./cmd/vendor/golang.org/x/telemetry/start.go:26: // ReportCrashes uses the [debug.SetCrashOutput] mechanism, which is a ./cmd/vendor/golang.org/x/telemetry/internal/counter/file.go:45: // counter pointers is reentrant: [file.invalidateCounters] may call ./cmd/vendor/golang.org/x/telemetry/internal/counter/file.go:46: // [file.lookup], which acquires mu. Therefore, writing current must be done ./cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go:60: ID string // e.g. "fmt [fmt.test]" ./cmd/vendor/golang.org/x/tools/go/analysis/analysis.go:53: // The [Pass.TypeErrors] field may consequently be non-empty. ./cmd/vendor/rsc.io/markdown/heading.go:18: // [Parser.HeadingIDs] is true and the heading ends with text like "{#id}". ./cmd/vendor/rsc.io/markdown/parse.go:169: // When a list item begins with the plain text [ ] or [x] ./runtime/trace/annotation.go:24: // The returned Task's [Task.End] method is used to mark the task's end. ./runtime/iface.go:27: entries [itabInitSize]*itab // really [size] large ./runtime/runtime2.go:925: // pcdata [npcdata]uint32 ./runtime/runtime2.go:934: // funcdata [nfuncdata]uint32 ./log/slog/handler.go:63: // [Logger] discards any errors from Handle. Wrap the Handle method to ./log/slog/handler.go:148: // The attribute's value has been resolved (see [Value.Resolve]). ./log/slog/record.go:34: // [runtime.CallersFrames]. In particular, it must not be passed to ./log/slog/record.go:35: // [runtime.FuncForPC]. ./os/exec/exec.go:186: // child process calls Go's [os.Getwd] or GNU C's ./io/fs/fs.go:29: // [File.Close] must be called to release any associated resources. ./io/fs/readlink.go:16: // Lstat returns a [FileInfo] describing the named file. ./io/fs/readlink.go:17: // If the file is a symbolic link, the returned [FileInfo] describes the symbolic link. ./io/pipe.go:159: // returned as err; otherwise err is [ErrClosedPipe]. ./reflect/type.go:252: // CanSeq reports whether a [Value] with this type can be iterated over using [Value.Seq]. ./reflect/type.go:255: // CanSeq2 reports whether a [Value] with this type can be iterated over using [Value.Seq2]. ./net/http/request.go:325: // Pattern is the [ServeMux] pattern that matched the request. ./net/http/http.go:191: // PushOptions describes options for [Pusher.Push]. ./net/http/httptrace/trace.go:22: // ContextClientTrace returns the [ClientTrace] associated with the ./net/http/server.go:98: // [ResponseWriter.WriteHeader]. The [Header] map also is the mechanism with which ./net/http/server.go:99: // [Handler] implementations can set HTTP trailers. ./net/http/server.go:101: // Changing the header map after a call to [ResponseWriter.WriteHeader] (or ./net/http/server.go:102: // [ResponseWriter.Write]) has no effect unless the HTTP status code was of the ./net/http/server.go:111: // keys not known to the [Handler] until after the first [ResponseWriter.Write], ./net/http/server.go:112: // is to prefix the [Header] map keys with the [TrailerPrefix] ./net/http/server.go:121: // If [ResponseWriter.WriteHeader] has not yet been called, Write calls ./net/http/server.go:125: // [DetectContentType]. Additionally, if the total size of all written ./net/http/server.go:264: // to [Hijacker] callers. It is usually of type *net.TCPConn or ./net/net.go:656: // temporaryError is an error type that implements the [Error] interface. ./net/net.go:666: UnwrapErr error // error returned by the [DNSError.Unwrap] method, might be nil ./sync/pool.go:54: local unsafe.Pointer // local fixed-size per-P pool, actual type is [P]poolLocal awk: warning: command line argument `./go/parser/testdata/issue42951/not_a_file.go' is a directory: skipped ./go/types/api.go:242: // expression F(int(1)) to the inferred type arguments [int], and resulting ./go/types/object.go:39: // Use [ObjectString] to control how package names are formatted in the string. ./go/doc/comment/print.go:36: // passed to [DocLink.DefaultURL] to construct a DocLink's URL. ./go/doc/comment/parse.go:192: // If LookupPackage(name) returns ok == true, then [name] ./go/doc/comment/parse.go:193: // (or [name.Sym] or [name.Sym.Method]) ./go/doc/comment/parse.go:199: // then [name] (or [name.Sym] or [name.Sym.Method]) ./go/doc/comment/parse.go:202: // of a package in the standard library, such as in [math] or [io.Reader]. ./go/doc/comment/parse.go:214: // If LookupSym("", "Name") returns true, then [Name] ./go/doc/comment/parse.go:218: // then [Recv.Name] is considered a documentation link for ./internal/abi/type.go:235: Moff uint32 // offset from this uncommontype to [mcount]Method ./internal/runtime/maps/group.go:238: // slots [abi.SwissMapGroupSlots]slot ./internal/poll/fd_windows.go:298: initPollable bool // value passed to [FD.Init] ./crypto/tls/ticket.go:63: // Extra is ignored by crypto/tls, but is encoded by [SessionState.Bytes] ./crypto/tls/ticket.go:64: // and parsed by [ParseSessionState]. ./crypto/tls/ticket.go:66: // This allows [Config.UnwrapSession]/[Config.WrapSession] and ./crypto/tls/ticket.go:67: // [ClientSessionCache] implementations to store and retrieve additional ./crypto/tls/common.go:251: // refers to elliptic curves for legacy reasons, see [CurveID]. If a legacy ./crypto/tls/common.go:429: // Section 4.2.7 and [CurveID]. ./crypto/tls/common.go:729: // previously produced by [WrapSession] into a usable session. ./crypto/tls/common.go:732: // (for example with [Config.EncryptTicket]), or use the ticket as a handle ./crypto/tls/common.go:733: // to recover a previously stored state. It must use [ParseSessionState] to ./crypto/tls/common.go:743: // WrapSession must serialize the session state with [SessionState.Bytes]. ./crypto/tls/common.go:745: // [Config.DecryptTicket]) and use it as the ticket, or store the state and ./crypto/tls/common.go:773: // The name refers to elliptic curves for legacy reasons, see [CurveID]. ./crypto/tls/common.go:778: // From Go 1.24, the default includes the [X25519MLKEM768] hybrid ./crypto/tls/common.go:877: // this to be the output of [ecdh.PrivateKey.Bytes]. ./crypto/tls/tls.go:126: // configuration; see the documentation of [Config] for the defaults. ./crypto/tls/tls.go:129: // use [Dialer.DialContext] with NetDialer set to the desired dialer. ./crypto/tls/quic.go:54: // [QUICStoreSession] and [QUICResumeSession] events for client connections. ./crypto/tls/quic.go:57: // The application should use [QUICConn.StoreSession] to store sessions. ./crypto/internal/fips140/rsa/rsa.go:35: // slices to be passed to [bigmod.Nat.Exp]. ./crypto/internal/fips140/drbg/rand.go:76: // [randutil.MaybeReadByte] and [fips140.RecordNonApproved] are called.
Comment From: thockin
xref https://github.com/golang/go/issues/59529