Skip to content

Commit 9a879c2

Browse files
committed
Preserve nil slices when converting between different slice types.
Prior to this change the following would evaluate to false: ``` type mySlice []byte _ = mySlice([]byte(nil)) == nil // Got: false, want: true ``` The fix is to check during conversion whether a slice is a nil slice and return nil slice of the desired type in that case. GopherJS uses sentinel values for nil slices, and technically they are are just regular zero-length slices.
1 parent a3e51e5 commit 9a879c2

File tree

4 files changed

+30
-2
lines changed

4 files changed

+30
-2
lines changed

compiler/expressions.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,7 @@ func (fc *funcContext) translateImplicitConversion(expr ast.Expr, desiredType ty
11541154

11551155
switch desiredType.Underlying().(type) {
11561156
case *types.Slice:
1157-
return fc.formatExpr("$subslice(new %1s(%2e.$array), %2e.$offset, %2e.$offset + %2e.$length)", fc.typeName(desiredType), expr)
1157+
return fc.formatExpr("$convertSliceType(%1e, %2s)", expr, fc.typeName(desiredType))
11581158

11591159
case *types.Interface:
11601160
if typesutil.IsJsObject(exprType) {

compiler/prelude/prelude.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,15 @@ var $sliceToGoArray = function(slice, arrayPtrType) {
180180
$throwRuntimeError("gopherjs: non-numeric slice to underlying array conversion is not supported for subslices");
181181
};
182182
183+
// Convert between compatible slice types (e.g. native and names).
184+
var $convertSliceType = function(slice, desiredType) {
185+
if (slice == slice.constructor.nil) {
186+
return desiredType.nil; // Preserve nil value.
187+
}
188+
189+
return $subslice(new desiredType(slice.$array), slice.$offset, slice.$offset + slice.$length);
190+
}
191+
183192
var $decodeRune = function(str, pos) {
184193
var c0 = str.charCodeAt(pos);
185194

compiler/prelude/prelude_min.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/misc_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,25 @@ func TestSlicingNilSlice(t *testing.T) {
666666
})
667667
}
668668

669+
func TestConvertingNilSlice(t *testing.T) {
670+
type mySlice []byte
671+
672+
a := []byte(nil)
673+
if a != nil {
674+
t.Errorf("[]byte(nil) != nil")
675+
}
676+
677+
b := mySlice(a)
678+
if b != nil {
679+
t.Errorf("mySlice([]byte(nil)) != nil")
680+
}
681+
682+
c := mySlice(nil)
683+
if c != nil {
684+
t.Errorf("mySlice(nil) != nil")
685+
}
686+
}
687+
669688
// Ensure that doing an interface conversion that fails
670689
// produces an expected error type with the right error text.
671690
func TestInterfaceConversionRuntimeError(t *testing.T) {

0 commit comments

Comments
 (0)