github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/src/go/types/issues_test.go (about) 1 // Copyright 2013 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 // This file implements tests for various issues. 6 7 package types_test 8 9 import ( 10 "fmt" 11 "go/ast" 12 "go/importer" 13 "go/parser" 14 "sort" 15 "strings" 16 "testing" 17 18 . "go/types" 19 ) 20 21 func TestIssue5770(t *testing.T) { 22 src := `package p; type S struct{T}` 23 f, err := parser.ParseFile(fset, "", src, 0) 24 if err != nil { 25 t.Fatal(err) 26 } 27 28 conf := Config{Importer: importer.Default()} 29 _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) // do not crash 30 want := "undeclared name: T" 31 if err == nil || !strings.Contains(err.Error(), want) { 32 t.Errorf("got: %v; want: %s", err, want) 33 } 34 } 35 36 func TestIssue5849(t *testing.T) { 37 src := ` 38 package p 39 var ( 40 s uint 41 _ = uint8(8) 42 _ = uint16(16) << s 43 _ = uint32(32 << s) 44 _ = uint64(64 << s + s) 45 _ = (interface{})("foo") 46 _ = (interface{})(nil) 47 )` 48 f, err := parser.ParseFile(fset, "", src, 0) 49 if err != nil { 50 t.Fatal(err) 51 } 52 53 var conf Config 54 types := make(map[ast.Expr]TypeAndValue) 55 _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types}) 56 if err != nil { 57 t.Fatal(err) 58 } 59 60 for x, tv := range types { 61 var want Type 62 switch x := x.(type) { 63 case *ast.BasicLit: 64 switch x.Value { 65 case `8`: 66 want = Typ[Uint8] 67 case `16`: 68 want = Typ[Uint16] 69 case `32`: 70 want = Typ[Uint32] 71 case `64`: 72 want = Typ[Uint] // because of "+ s", s is of type uint 73 case `"foo"`: 74 want = Typ[String] 75 } 76 case *ast.Ident: 77 if x.Name == "nil" { 78 want = Typ[UntypedNil] 79 } 80 } 81 if want != nil && !Identical(tv.Type, want) { 82 t.Errorf("got %s; want %s", tv.Type, want) 83 } 84 } 85 } 86 87 func TestIssue6413(t *testing.T) { 88 src := ` 89 package p 90 func f() int { 91 defer f() 92 go f() 93 return 0 94 } 95 ` 96 f, err := parser.ParseFile(fset, "", src, 0) 97 if err != nil { 98 t.Fatal(err) 99 } 100 101 var conf Config 102 types := make(map[ast.Expr]TypeAndValue) 103 _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types}) 104 if err != nil { 105 t.Fatal(err) 106 } 107 108 want := Typ[Int] 109 n := 0 110 for x, tv := range types { 111 if _, ok := x.(*ast.CallExpr); ok { 112 if tv.Type != want { 113 t.Errorf("%s: got %s; want %s", fset.Position(x.Pos()), tv.Type, want) 114 } 115 n++ 116 } 117 } 118 119 if n != 2 { 120 t.Errorf("got %d CallExprs; want 2", n) 121 } 122 } 123 124 func TestIssue7245(t *testing.T) { 125 src := ` 126 package p 127 func (T) m() (res bool) { return } 128 type T struct{} // receiver type after method declaration 129 ` 130 f, err := parser.ParseFile(fset, "", src, 0) 131 if err != nil { 132 t.Fatal(err) 133 } 134 135 var conf Config 136 defs := make(map[*ast.Ident]Object) 137 _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs}) 138 if err != nil { 139 t.Fatal(err) 140 } 141 142 m := f.Decls[0].(*ast.FuncDecl) 143 res1 := defs[m.Name].(*Func).Type().(*Signature).Results().At(0) 144 res2 := defs[m.Type.Results.List[0].Names[0]].(*Var) 145 146 if res1 != res2 { 147 t.Errorf("got %s (%p) != %s (%p)", res1, res2, res1, res2) 148 } 149 } 150 151 // This tests that uses of existing vars on the LHS of an assignment 152 // are Uses, not Defs; and also that the (illegal) use of a non-var on 153 // the LHS of an assignment is a Use nonetheless. 154 func TestIssue7827(t *testing.T) { 155 const src = ` 156 package p 157 func _() { 158 const w = 1 // defs w 159 x, y := 2, 3 // defs x, y 160 w, x, z := 4, 5, 6 // uses w, x, defs z; error: cannot assign to w 161 _, _, _ = x, y, z // uses x, y, z 162 } 163 ` 164 const want = `L3 defs func p._() 165 L4 defs const w untyped int 166 L5 defs var x int 167 L5 defs var y int 168 L6 defs var z int 169 L6 uses const w untyped int 170 L6 uses var x int 171 L7 uses var x int 172 L7 uses var y int 173 L7 uses var z int` 174 175 f, err := parser.ParseFile(fset, "", src, 0) 176 if err != nil { 177 t.Fatal(err) 178 } 179 180 // don't abort at the first error 181 conf := Config{Error: func(err error) { t.Log(err) }} 182 defs := make(map[*ast.Ident]Object) 183 uses := make(map[*ast.Ident]Object) 184 _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs, Uses: uses}) 185 if s := fmt.Sprint(err); !strings.HasSuffix(s, "cannot assign to w") { 186 t.Errorf("Check: unexpected error: %s", s) 187 } 188 189 var facts []string 190 for id, obj := range defs { 191 if obj != nil { 192 fact := fmt.Sprintf("L%d defs %s", fset.Position(id.Pos()).Line, obj) 193 facts = append(facts, fact) 194 } 195 } 196 for id, obj := range uses { 197 fact := fmt.Sprintf("L%d uses %s", fset.Position(id.Pos()).Line, obj) 198 facts = append(facts, fact) 199 } 200 sort.Strings(facts) 201 202 got := strings.Join(facts, "\n") 203 if got != want { 204 t.Errorf("Unexpected defs/uses\ngot:\n%s\nwant:\n%s", got, want) 205 } 206 }