Go: cmd/go: go refuses to compile hex floats on +build go1.13 file

Created on 19 Apr 2020  路  20Comments  路  Source: golang/go

What version of Go are you using (go version)?

$ go version
go version go1.13.10 linux/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="/home/karl/.cache/go-build"
GOENV="/home/karl/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/karl/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/karl/tmp/floattest/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build659173498=/tmp/go-build -gno-record-gcc-switches"

What did you do?

go.mod:

module floattest

go 1.11

main.go:

package floattest

func returnFloat(v float64) float64 {
    return v
}

main_1_13_test.go:

// +build go1.13

package floattest

import (
    "testing"
)

func TestStuff(t *testing.T) {
    expected := 0x1.5fp20
    actual := returnFloat(expected)
    if actual != expected {
        t.Errorf("Expected %v but got %v\n", expected, actual)
    }
}

command: go test

What did you expect to see?

ok      floattest   0.002s

What did you see instead?

# floattest [floattest.test]
./main_1_13_test.go:10:14: hexadecimal floating-point literals requires go1.13 or later (-lang was set to go1.11; check go.mod)
FAIL    floattest [build failed]

Since the build settings will not compile this file on go < 1.13, this shouldn't be an error.

GoCommand NeedsInvestigation

Most helpful comment

I think this should work. Having a go1.11 mark in the mod file means we shouldn't define a go1.13 build tag.
The bad code never makes it to the compiler. Something earlier in the toolchain is barfing on the input.

@bcmills

All 20 comments

But you use go.1.13.10 to run go test, so the file is built.

Yes, so there should be no error, since go 1.13 supports hex float notation.

You specified go 1.11 in go.mod, so I'd say that's expected, it'd actually be a bug if it worked.

So how to I make my project buildable under 1.11? I've put the 1.13 stuff in a +build guarded file so that it only builds the 1.13 stuff when building with go 1.13.

So how to I make my project buildable under 1.11? I've put the 1.13 stuff in a +build guarded file so that it only builds the 1.13 stuff when building with go 1.13.

Use go1.11.x or 1.12.x to build.

Or maybe drop support for go < 1.13, set go1.13 in go.mod

It builds fine under 1.11 and 1.12. It only fails when I try to build using 1.13.

Dropping support for 1.11 and 1.12 seems a silly thing to do when it builds fine under those versions. This is a problem with two compiler rules fighting each other, not a rational thing.

I think this should work. Having a go1.11 mark in the mod file means we shouldn't define a go1.13 build tag.
The bad code never makes it to the compiler. Something earlier in the toolchain is barfing on the input.

@bcmills

It builds fine under 1.11 and 1.12. It only fails when I try to build using 1.13.

Dropping support for 1.11 and 1.12 seems a silly thing to do when it builds fine under those versions. This is a problem with two compiler rules fighting each other, not a rational thing.

I don't think it's silly.

Go is backward compatible, and also go1.11 and 1.12 are not supported anymore (see release policy)

@randall77 How about passing the current go version to -lang if the version is greater than the one specific in go.mod?

@kstenerud Doesn't doing something like this work for you? https://play.golang.org/p/nqejHFvguRv

-- go.mod --
module play.ground

go 1.13

@kortschak Change this to 1.11 and the problem returns.

So don't change it to go1.11? When you have go1.11 in the Go version specifier you are saying you want to use Go 1.11 features, but hex floats are a Go 1.13 feature.

Then that defeats the whole purpose. If go.mod specifies 1.13, then you can't build for <1.13, and foo_old.go is completely pointless since // +build !go1.13 will never be built.

The point is that I want to have my software package buildable in 1.11 and 1.12, but also use hex floats for more specific floating point test code when building in 1.13+.

More specifically: this code doesn't take the current +build settings into account to determine that the currently compiling file (with // +build go1.13) is restricted to 1.13 and up, but rather just fails based on the -lang flag.

Then that defeats the whole purpose. If go.mod specifies 1.13, then you can't build for <1.13, and foo_old.go is completely pointless since // +build !go1.13 will never be built.

This is not true. In the following session I build and run the code in the playground (with the exception that the float literal is negated in foo_old.go so that the code used is identified) in each version of Go from 1.11.9 to 1.14.2 (build chain is rebuilt for each version in another term).

~/foo $ go version
go version go1.11.9 linux/amd64
~/foo $ go build .
~/foo $ ./play.ground 
-1.437696e+06
~/foo $ go version
go version go1.12.9 linux/amd64
~/foo $ go build .
~/foo $ ./play.ground 
-1.437696e+06
~/foo $ go version
go version go1.13.9 linux/amd64
~/foo $ go build .
~/foo $ ./play.ground 
1.437696e+06
~/foo $ go version
go version go1.14.2 linux/amd64
~/foo $ go build .
~/foo $ ./play.ground 
1.437696e+06

Then this is exposing another issue. If go.mod specifies 1.13, why are the go 1.11 and 1.12 compilers not detecting this and throwing an error?

If the version in go.mod is ignored by the compiler, what's it for?

It is to indicate language features that are required. The question you are asking is #30791.

Duplicate of #30791

Was this page helpful?
0 / 5 - 0 ratings