github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/go/ssa/const_test.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ssa_test 6 7 import ( 8 "go/ast" 9 "go/constant" 10 "go/parser" 11 "go/token" 12 "go/types" 13 "math/big" 14 "strings" 15 "testing" 16 17 "golang.org/x/tools/go/ssa" 18 "golang.org/x/tools/internal/typeparams" 19 ) 20 21 func TestConstString(t *testing.T) { 22 if !typeparams.Enabled { 23 t.Skip("TestConstString requires type parameters.") 24 } 25 26 const source = ` 27 package P 28 29 type Named string 30 31 func fn() (int, bool, string) 32 func gen[T int]() {} 33 ` 34 fset := token.NewFileSet() 35 f, err := parser.ParseFile(fset, "p.go", source, 0) 36 if err != nil { 37 t.Fatal(err) 38 } 39 40 var conf types.Config 41 pkg, err := conf.Check("P", fset, []*ast.File{f}, nil) 42 if err != nil { 43 t.Fatal(err) 44 } 45 46 for _, test := range []struct { 47 expr string // type expression 48 constant interface{} // constant value 49 want string // expected String() value 50 }{ 51 {"int", int64(0), "0:int"}, 52 {"int64", int64(0), "0:int64"}, 53 {"float32", int64(0), "0:float32"}, 54 {"float32", big.NewFloat(1.5), "1.5:float32"}, 55 {"bool", false, "false:bool"}, 56 {"string", "", `"":string`}, 57 {"Named", "", `"":P.Named`}, 58 {"struct{x string}", nil, "struct{x string}{}:struct{x string}"}, 59 {"[]int", nil, "nil:[]int"}, 60 {"[3]int", nil, "[3]int{}:[3]int"}, 61 {"*int", nil, "nil:*int"}, 62 {"interface{}", nil, "nil:interface{}"}, 63 {"interface{string}", nil, `"":interface{string}`}, 64 {"interface{int|int64}", nil, "0:interface{int|int64}"}, 65 {"interface{bool}", nil, "false:interface{bool}"}, 66 {"interface{bool|int}", nil, "nil:interface{bool|int}"}, 67 {"interface{int|string}", nil, "nil:interface{int|string}"}, 68 {"interface{bool|string}", nil, "nil:interface{bool|string}"}, 69 {"interface{struct{x string}}", nil, "nil:interface{struct{x string}}"}, 70 {"interface{int|int64}", int64(1), "1:interface{int|int64}"}, 71 {"interface{~bool}", true, "true:interface{~bool}"}, 72 {"interface{Named}", "lorem ipsum", `"lorem ipsum":interface{P.Named}`}, 73 {"func() (int, bool, string)", nil, "nil:func() (int, bool, string)"}, 74 } { 75 // Eval() expr for its type. 76 tv, err := types.Eval(fset, pkg, 0, test.expr) 77 if err != nil { 78 t.Fatalf("Eval(%s) failed: %v", test.expr, err) 79 } 80 var val constant.Value 81 if test.constant != nil { 82 val = constant.Make(test.constant) 83 } 84 c := ssa.NewConst(val, tv.Type) 85 got := strings.ReplaceAll(c.String(), " | ", "|") // Accept both interface{a | b} and interface{a|b}. 86 if got != test.want { 87 t.Errorf("ssa.NewConst(%v, %s).String() = %v, want %v", val, tv.Type, got, test.want) 88 } 89 } 90 91 // Test tuples 92 fn := pkg.Scope().Lookup("fn") 93 tup := fn.Type().(*types.Signature).Results() 94 if got, want := ssa.NewConst(nil, tup).String(), `(0, false, ""):(int, bool, string)`; got != want { 95 t.Errorf("ssa.NewConst(%v, %s).String() = %v, want %v", nil, tup, got, want) 96 } 97 98 // Test type-param 99 gen := pkg.Scope().Lookup("gen") 100 tp := typeparams.ForSignature(gen.Type().(*types.Signature)).At(0) 101 if got, want := ssa.NewConst(nil, tp).String(), "0:T"; got != want { 102 t.Errorf("ssa.NewConst(%v, %s).String() = %v, want %v", nil, tup, got, want) 103 } 104 }