Skip to content

Slice unpacking to variadic function not honored #29767

Closed
@ghost

Description

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

go1.10.4 linux/amd64

Does this issue reproduce with the latest release?

Haven't tried.

What operating system and processor architecture are you using (go env)?

go env Output
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/<>/.cache/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/<>/go"
GORACE=""
GOROOT="/usr/lib/go-1.10"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go-1.10/pkg/tool/linux_amd64"
GCCGO="/usr/bin/gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
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-build779194954=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Defined function with signature: func variadic(args ...interface{}) and attempted to call it by unpacking a slice: variadic([]int{1,2,3}...).

What did you expect to see?

Compilation succeeds.

What did you see instead?

Conversion error from []int to []interface{}.

The reason why is understood, as per FAQ:

If the final argument is assignable to a slice type []T, it may be passed unchanged as the value for a ...T parameter if the argument is followed by .... In this case no new slice is created.

However, the first sentence suggests that this optimization should not have occurred because []int is not assignable to []interface{}:

A value x is assignable to a variable of type T ("x is assignable to T") if one of the following conditions applies:
x's type is identical to T

False, []int is not of type []interface{}.

x's type V and T have identical underlying types and at least one of V or T is not a defined type.

False, both types are defined.

T is an interface type and x implements T.

False, []int is not an interface.

x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a defined type.

False, []int is not a channel.

x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.

False, []int is not nil.

x is an untyped constant representable by a value of type T.

False, []int is a type.

Since []int is not assignable to []interface{} the slice should have been unpacked and each element passed individually to the variadic function.

There are several related issues (eg. #1616, #18547, #27795) that expose the same problem, probably more but none appear to go further than claiming that this is "working as intended".

If I wanted to pass the []int as-is, I could have simply omitted unpacking by writing variadic([]int{1,2,3}) instead of variadic([]int{1,2,3}...). By typing the latter, I explicitly say "I want to unpack this slice". The compiler however decided to take my statement as suggestion since it believed []int is assignable to []interface{} and decided not to not honor my request, instead passing the slice as-is.

I this believe is in error.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions