golang.org/x/tools@v0.21.1-0.20240520172518-788d39e776b1/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 ) 19 20 func TestConstString(t *testing.T) { 21 const source = ` 22 package P 23 24 type Named string 25 26 func fn() (int, bool, string) 27 func gen[T int]() {} 28 ` 29 fset := token.NewFileSet() 30 f, err := parser.ParseFile(fset, "p.go", source, 0) 31 if err != nil { 32 t.Fatal(err) 33 } 34 35 var conf types.Config 36 pkg, err := conf.Check("P", fset, []*ast.File{f}, nil) 37 if err != nil { 38 t.Fatal(err) 39 } 40 41 for _, test := range []struct { 42 expr string // type expression 43 constant interface{} // constant value 44 want string // expected String() value 45 }{ 46 {"int", int64(0), "0:int"}, 47 {"int64", int64(0), "0:int64"}, 48 {"float32", int64(0), "0:float32"}, 49 {"float32", big.NewFloat(1.5), "1.5:float32"}, 50 {"bool", false, "false:bool"}, 51 {"string", "", `"":string`}, 52 {"Named", "", `"":P.Named`}, 53 {"struct{x string}", nil, "struct{x string}{}:struct{x string}"}, 54 {"[]int", nil, "nil:[]int"}, 55 {"[3]int", nil, "[3]int{}:[3]int"}, 56 {"*int", nil, "nil:*int"}, 57 {"interface{}", nil, "nil:interface{}"}, 58 {"interface{string}", nil, `"":interface{string}`}, 59 {"interface{int|int64}", nil, "0:interface{int|int64}"}, 60 {"interface{bool}", nil, "false:interface{bool}"}, 61 {"interface{bool|int}", nil, "nil:interface{bool|int}"}, 62 {"interface{int|string}", nil, "nil:interface{int|string}"}, 63 {"interface{bool|string}", nil, "nil:interface{bool|string}"}, 64 {"interface{struct{x string}}", nil, "nil:interface{struct{x string}}"}, 65 {"interface{int|int64}", int64(1), "1:interface{int|int64}"}, 66 {"interface{~bool}", true, "true:interface{~bool}"}, 67 {"interface{Named}", "lorem ipsum", `"lorem ipsum":interface{P.Named}`}, 68 {"func() (int, bool, string)", nil, "nil:func() (int, bool, string)"}, 69 } { 70 // Eval() expr for its type. 71 tv, err := types.Eval(fset, pkg, 0, test.expr) 72 if err != nil { 73 t.Fatalf("Eval(%s) failed: %v", test.expr, err) 74 } 75 var val constant.Value 76 if test.constant != nil { 77 val = constant.Make(test.constant) 78 } 79 c := ssa.NewConst(val, tv.Type) 80 got := strings.ReplaceAll(c.String(), " | ", "|") // Accept both interface{a | b} and interface{a|b}. 81 if got != test.want { 82 t.Errorf("ssa.NewConst(%v, %s).String() = %v, want %v", val, tv.Type, got, test.want) 83 } 84 } 85 86 // Test tuples 87 fn := pkg.Scope().Lookup("fn") 88 tup := fn.Type().(*types.Signature).Results() 89 if got, want := ssa.NewConst(nil, tup).String(), `(0, false, ""):(int, bool, string)`; got != want { 90 t.Errorf("ssa.NewConst(%v, %s).String() = %v, want %v", nil, tup, got, want) 91 } 92 93 // Test type-param 94 gen := pkg.Scope().Lookup("gen") 95 tp := gen.Type().(*types.Signature).TypeParams().At(0) 96 if got, want := ssa.NewConst(nil, tp).String(), "0:T"; got != want { 97 t.Errorf("ssa.NewConst(%v, %s).String() = %v, want %v", nil, tup, got, want) 98 } 99 }