diff options
author | Dan Scales <danscales@google.com> | 2021-06-02 00:03:25 -0700 |
---|---|---|
committer | Dan Scales <danscales@google.com> | 2021-06-02 23:10:42 +0000 |
commit | 97cb0113a358a24931bc91c956da0cb023f2776c (patch) | |
tree | 0baa45bac527ebaecc3b0eee3e1de3ac53b4cca1 /src/cmd/compile/internal/typecheck/iexport.go | |
parent | 6b1cdeaef3099b32d244cef7bb5adc4d7b7628fc (diff) | |
download | go-97cb0113a358a24931bc91c956da0cb023f2776c.tar.gz go-97cb0113a358a24931bc91c956da0cb023f2776c.zip |
[dev.typeparams] cmd/compile: fix export/import of constants with typeparam type
A constant will have a TYPEPARAM type if it appears in a place where it
must match that typeparam type (e.g. in a binary operation with a
variable of that typeparam type). If so, then we must write out its
actual constant kind as well, so its constant val can be read in
properly during import.
Fixed some export/import tests which were casting some untyped constants
to avoid this problem.
Change-Id: I285ad8f1c8febbe526769c96e6b27acbd23050f0
Reviewed-on: https://go-review.googlesource.com/c/go/+/324189
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Diffstat (limited to 'src/cmd/compile/internal/typecheck/iexport.go')
-rw-r--r-- | src/cmd/compile/internal/typecheck/iexport.go | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index d83f385fcb..66c356ee7c 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1061,26 +1061,50 @@ func constTypeOf(typ *types.Type) constant.Kind { } func (w *exportWriter) value(typ *types.Type, v constant.Value) { - ir.AssertValidTypeForConst(typ, v) w.typ(typ) + var kind constant.Kind + var valType *types.Type + + if typ.Kind() == types.TTYPEPARAM { + // A constant will have a TYPEPARAM type if it appears in a place + // where it must match that typeparam type (e.g. in a binary + // operation with a variable of that typeparam type). If so, then + // we must write out its actual constant kind as well, so its + // constant val can be read in properly during import. + kind = v.Kind() + w.int64(int64(kind)) + + switch kind { + case constant.Int: + valType = types.Types[types.TINT64] + case constant.Float: + valType = types.Types[types.TFLOAT64] + case constant.Complex: + valType = types.Types[types.TCOMPLEX128] + } + } else { + ir.AssertValidTypeForConst(typ, v) + kind = constTypeOf(typ) + valType = typ + } - // Each type has only one admissible constant representation, - // so we could type switch directly on v.U here. However, - // switching on the type increases symmetry with import logic - // and provides a useful consistency check. + // Each type has only one admissible constant representation, so we could + // type switch directly on v.Kind() here. However, switching on the type + // (in the non-typeparam case) increases symmetry with import logic and + // provides a useful consistency check. - switch constTypeOf(typ) { + switch kind { case constant.Bool: w.bool(constant.BoolVal(v)) case constant.String: w.string(constant.StringVal(v)) case constant.Int: - w.mpint(v, typ) + w.mpint(v, valType) case constant.Float: - w.mpfloat(v, typ) + w.mpfloat(v, valType) case constant.Complex: - w.mpfloat(constant.Real(v), typ) - w.mpfloat(constant.Imag(v), typ) + w.mpfloat(constant.Real(v), valType) + w.mpfloat(constant.Imag(v), valType) } } |