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  }