...

Source file src/golang.org/x/tools/refactor/satisfy/find.go

Documentation: golang.org/x/tools/refactor/satisfy

     1  // Copyright 2014 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 satisfy inspects the type-checked ASTs of Go packages and
     6  // reports the set of discovered type constraints of the form (lhs, rhs
     7  // Type) where lhs is a non-trivial interface, rhs satisfies this
     8  // interface, and this fact is necessary for the package to be
     9  // well-typed.
    10  //
    11  // THIS PACKAGE IS EXPERIMENTAL AND MAY CHANGE AT ANY TIME.
    12  //
    13  // It is provided only for the gopls tool. It requires well-typed inputs.
    14  package satisfy // import "golang.org/x/tools/refactor/satisfy"
    15  
    16  // NOTES:
    17  //
    18  // We don't care about numeric conversions, so we don't descend into
    19  // types or constant expressions.  This is unsound because
    20  // constant expressions can contain arbitrary statements, e.g.
    21  //   const x = len([1]func(){func() {
    22  //     ...
    23  //   }})
    24  //
    25  // Assignability conversions are possible in the following places:
    26  // - in assignments y = x, y := x, var y = x.
    27  // - from call argument types to formal parameter types
    28  // - in append and delete calls
    29  // - from return operands to result parameter types
    30  // - in composite literal T{k:v}, from k and v to T's field/element/key type
    31  // - in map[key] from key to the map's key type
    32  // - in comparisons x==y and switch x { case y: }.
    33  // - in explicit conversions T(x)
    34  // - in sends ch <- x, from x to the channel element type
    35  // - in type assertions x.(T) and switch x.(type) { case T: }
    36  //
    37  // The results of this pass provide information equivalent to the
    38  // ssa.MakeInterface and ssa.ChangeInterface instructions.
    39  
    40  import (
    41  	"fmt"
    42  	"go/ast"
    43  	"go/token"
    44  	"go/types"
    45  
    46  	"golang.org/x/tools/go/ast/astutil"
    47  	"golang.org/x/tools/go/types/typeutil"
    48  	"golang.org/x/tools/internal/typeparams"
    49  )
    50  
    51  // A Constraint records the fact that the RHS type does and must
    52  // satisfy the LHS type, which is an interface.
    53  // The names are suggestive of an assignment statement LHS = RHS.
    54  //
    55  // The constraint is implicitly universally quantified over any type
    56  // parameters appearing within the two types.
    57  type Constraint struct {
    58  	LHS, RHS types.Type
    59  }
    60  
    61  // A Finder inspects the type-checked ASTs of Go packages and
    62  // accumulates the set of type constraints (x, y) such that x is
    63  // assignable to y, y is an interface, and both x and y have methods.
    64  //
    65  // In other words, it returns the subset of the "implements" relation
    66  // that is checked during compilation of a package.  Refactoring tools
    67  // will need to preserve at least this part of the relation to ensure
    68  // continued compilation.
    69  type Finder struct {
    70  	Result    map[Constraint]bool
    71  	msetcache typeutil.MethodSetCache
    72  
    73  	// per-Find state
    74  	info *types.Info
    75  	sig  *types.Signature
    76  }
    77  
    78  // Find inspects a single package, populating Result with its pairs of
    79  // constrained types.
    80  //
    81  // The result is non-canonical and thus may contain duplicates (but this
    82  // tends to preserves names of interface types better).
    83  //
    84  // The package must be free of type errors, and
    85  // info.{Defs,Uses,Selections,Types} must have been populated by the
    86  // type-checker.
    87  func (f *Finder) Find(info *types.Info, files []*ast.File) {
    88  	if f.Result == nil {
    89  		f.Result = make(map[Constraint]bool)
    90  	}
    91  
    92  	f.info = info
    93  	for _, file := range files {
    94  		for _, d := range file.Decls {
    95  			switch d := d.(type) {
    96  			case *ast.GenDecl:
    97  				if d.Tok == token.VAR { // ignore consts
    98  					for _, spec := range d.Specs {
    99  						f.valueSpec(spec.(*ast.ValueSpec))
   100  					}
   101  				}
   102  
   103  			case *ast.FuncDecl:
   104  				if d.Body != nil {
   105  					f.sig = f.info.Defs[d.Name].Type().(*types.Signature)
   106  					f.stmt(d.Body)
   107  					f.sig = nil
   108  				}
   109  			}
   110  		}
   111  	}
   112  	f.info = nil
   113  }
   114  
   115  var (
   116  	tInvalid     = types.Typ[types.Invalid]
   117  	tUntypedBool = types.Typ[types.UntypedBool]
   118  	tUntypedNil  = types.Typ[types.UntypedNil]
   119  )
   120  
   121  // exprN visits an expression in a multi-value context.
   122  func (f *Finder) exprN(e ast.Expr) types.Type {
   123  	typ := f.info.Types[e].Type.(*types.Tuple)
   124  	switch e := e.(type) {
   125  	case *ast.ParenExpr:
   126  		return f.exprN(e.X)
   127  
   128  	case *ast.CallExpr:
   129  		// x, err := f(args)
   130  		sig := coreType(f.expr(e.Fun)).(*types.Signature)
   131  		f.call(sig, e.Args)
   132  
   133  	case *ast.IndexExpr:
   134  		// y, ok := x[i]
   135  		x := f.expr(e.X)
   136  		f.assign(f.expr(e.Index), coreType(x).(*types.Map).Key())
   137  
   138  	case *ast.TypeAssertExpr:
   139  		// y, ok := x.(T)
   140  		f.typeAssert(f.expr(e.X), typ.At(0).Type())
   141  
   142  	case *ast.UnaryExpr: // must be receive <-
   143  		// y, ok := <-x
   144  		f.expr(e.X)
   145  
   146  	default:
   147  		panic(e)
   148  	}
   149  	return typ
   150  }
   151  
   152  func (f *Finder) call(sig *types.Signature, args []ast.Expr) {
   153  	if len(args) == 0 {
   154  		return
   155  	}
   156  
   157  	// Ellipsis call?  e.g. f(x, y, z...)
   158  	if _, ok := args[len(args)-1].(*ast.Ellipsis); ok {
   159  		for i, arg := range args {
   160  			// The final arg is a slice, and so is the final param.
   161  			f.assign(sig.Params().At(i).Type(), f.expr(arg))
   162  		}
   163  		return
   164  	}
   165  
   166  	var argtypes []types.Type
   167  
   168  	// Gather the effective actual parameter types.
   169  	if tuple, ok := f.info.Types[args[0]].Type.(*types.Tuple); ok {
   170  		// f(g()) call where g has multiple results?
   171  		f.expr(args[0])
   172  		// unpack the tuple
   173  		for i := 0; i < tuple.Len(); i++ {
   174  			argtypes = append(argtypes, tuple.At(i).Type())
   175  		}
   176  	} else {
   177  		for _, arg := range args {
   178  			argtypes = append(argtypes, f.expr(arg))
   179  		}
   180  	}
   181  
   182  	// Assign the actuals to the formals.
   183  	if !sig.Variadic() {
   184  		for i, argtype := range argtypes {
   185  			f.assign(sig.Params().At(i).Type(), argtype)
   186  		}
   187  	} else {
   188  		// The first n-1 parameters are assigned normally.
   189  		nnormals := sig.Params().Len() - 1
   190  		for i, argtype := range argtypes[:nnormals] {
   191  			f.assign(sig.Params().At(i).Type(), argtype)
   192  		}
   193  		// Remaining args are assigned to elements of varargs slice.
   194  		tElem := sig.Params().At(nnormals).Type().(*types.Slice).Elem()
   195  		for i := nnormals; i < len(argtypes); i++ {
   196  			f.assign(tElem, argtypes[i])
   197  		}
   198  	}
   199  }
   200  
   201  // builtin visits the arguments of a builtin type with signature sig.
   202  func (f *Finder) builtin(obj *types.Builtin, sig *types.Signature, args []ast.Expr) {
   203  	switch obj.Name() {
   204  	case "make", "new":
   205  		// skip the type operand
   206  		for _, arg := range args[1:] {
   207  			f.expr(arg)
   208  		}
   209  
   210  	case "append":
   211  		s := f.expr(args[0])
   212  		if _, ok := args[len(args)-1].(*ast.Ellipsis); ok && len(args) == 2 {
   213  			// append(x, y...)   including append([]byte, "foo"...)
   214  			f.expr(args[1])
   215  		} else {
   216  			// append(x, y, z)
   217  			tElem := coreType(s).(*types.Slice).Elem()
   218  			for _, arg := range args[1:] {
   219  				f.assign(tElem, f.expr(arg))
   220  			}
   221  		}
   222  
   223  	case "delete":
   224  		m := f.expr(args[0])
   225  		k := f.expr(args[1])
   226  		f.assign(coreType(m).(*types.Map).Key(), k)
   227  
   228  	default:
   229  		// ordinary call
   230  		f.call(sig, args)
   231  	}
   232  }
   233  
   234  func (f *Finder) extract(tuple types.Type, i int) types.Type {
   235  	if tuple, ok := tuple.(*types.Tuple); ok && i < tuple.Len() {
   236  		return tuple.At(i).Type()
   237  	}
   238  	return tInvalid
   239  }
   240  
   241  func (f *Finder) valueSpec(spec *ast.ValueSpec) {
   242  	var T types.Type
   243  	if spec.Type != nil {
   244  		T = f.info.Types[spec.Type].Type
   245  	}
   246  	switch len(spec.Values) {
   247  	case len(spec.Names): // e.g. var x, y = f(), g()
   248  		for _, value := range spec.Values {
   249  			v := f.expr(value)
   250  			if T != nil {
   251  				f.assign(T, v)
   252  			}
   253  		}
   254  
   255  	case 1: // e.g. var x, y = f()
   256  		tuple := f.exprN(spec.Values[0])
   257  		for i := range spec.Names {
   258  			if T != nil {
   259  				f.assign(T, f.extract(tuple, i))
   260  			}
   261  		}
   262  	}
   263  }
   264  
   265  // assign records pairs of distinct types that are related by
   266  // assignability, where the left-hand side is an interface and both
   267  // sides have methods.
   268  //
   269  // It should be called for all assignability checks, type assertions,
   270  // explicit conversions and comparisons between two types, unless the
   271  // types are uninteresting (e.g. lhs is a concrete type, or the empty
   272  // interface; rhs has no methods).
   273  func (f *Finder) assign(lhs, rhs types.Type) {
   274  	if types.Identical(lhs, rhs) {
   275  		return
   276  	}
   277  	if !isInterface(lhs) {
   278  		return
   279  	}
   280  
   281  	if f.msetcache.MethodSet(lhs).Len() == 0 {
   282  		return
   283  	}
   284  	if f.msetcache.MethodSet(rhs).Len() == 0 {
   285  		return
   286  	}
   287  	// record the pair
   288  	f.Result[Constraint{lhs, rhs}] = true
   289  }
   290  
   291  // typeAssert must be called for each type assertion x.(T) where x has
   292  // interface type I.
   293  func (f *Finder) typeAssert(I, T types.Type) {
   294  	// Type assertions are slightly subtle, because they are allowed
   295  	// to be "impossible", e.g.
   296  	//
   297  	// 	var x interface{f()}
   298  	//	_ = x.(interface{f()int}) // legal
   299  	//
   300  	// (In hindsight, the language spec should probably not have
   301  	// allowed this, but it's too late to fix now.)
   302  	//
   303  	// This means that a type assert from I to T isn't exactly a
   304  	// constraint that T is assignable to I, but for a refactoring
   305  	// tool it is a conditional constraint that, if T is assignable
   306  	// to I before a refactoring, it should remain so after.
   307  
   308  	if types.AssignableTo(T, I) {
   309  		f.assign(I, T)
   310  	}
   311  }
   312  
   313  // compare must be called for each comparison x==y.
   314  func (f *Finder) compare(x, y types.Type) {
   315  	if types.AssignableTo(x, y) {
   316  		f.assign(y, x)
   317  	} else if types.AssignableTo(y, x) {
   318  		f.assign(x, y)
   319  	}
   320  }
   321  
   322  // expr visits a true expression (not a type or defining ident)
   323  // and returns its type.
   324  func (f *Finder) expr(e ast.Expr) types.Type {
   325  	tv := f.info.Types[e]
   326  	if tv.Value != nil {
   327  		return tv.Type // prune the descent for constants
   328  	}
   329  
   330  	// tv.Type may be nil for an ast.Ident.
   331  
   332  	switch e := e.(type) {
   333  	case *ast.BadExpr, *ast.BasicLit:
   334  		// no-op
   335  
   336  	case *ast.Ident:
   337  		// (referring idents only)
   338  		if obj, ok := f.info.Uses[e]; ok {
   339  			return obj.Type()
   340  		}
   341  		if e.Name == "_" { // e.g. "for _ = range x"
   342  			return tInvalid
   343  		}
   344  		panic("undefined ident: " + e.Name)
   345  
   346  	case *ast.Ellipsis:
   347  		if e.Elt != nil {
   348  			f.expr(e.Elt)
   349  		}
   350  
   351  	case *ast.FuncLit:
   352  		saved := f.sig
   353  		f.sig = tv.Type.(*types.Signature)
   354  		f.stmt(e.Body)
   355  		f.sig = saved
   356  
   357  	case *ast.CompositeLit:
   358  		// No need for coreType here: go1.18 disallows P{...} for type param P.
   359  		switch T := deref(tv.Type).Underlying().(type) {
   360  		case *types.Struct:
   361  			for i, elem := range e.Elts {
   362  				if kv, ok := elem.(*ast.KeyValueExpr); ok {
   363  					f.assign(f.info.Uses[kv.Key.(*ast.Ident)].Type(), f.expr(kv.Value))
   364  				} else {
   365  					f.assign(T.Field(i).Type(), f.expr(elem))
   366  				}
   367  			}
   368  
   369  		case *types.Map:
   370  			for _, elem := range e.Elts {
   371  				elem := elem.(*ast.KeyValueExpr)
   372  				f.assign(T.Key(), f.expr(elem.Key))
   373  				f.assign(T.Elem(), f.expr(elem.Value))
   374  			}
   375  
   376  		case *types.Array, *types.Slice:
   377  			tElem := T.(interface {
   378  				Elem() types.Type
   379  			}).Elem()
   380  			for _, elem := range e.Elts {
   381  				if kv, ok := elem.(*ast.KeyValueExpr); ok {
   382  					// ignore the key
   383  					f.assign(tElem, f.expr(kv.Value))
   384  				} else {
   385  					f.assign(tElem, f.expr(elem))
   386  				}
   387  			}
   388  
   389  		default:
   390  			panic("unexpected composite literal type: " + tv.Type.String())
   391  		}
   392  
   393  	case *ast.ParenExpr:
   394  		f.expr(e.X)
   395  
   396  	case *ast.SelectorExpr:
   397  		if _, ok := f.info.Selections[e]; ok {
   398  			f.expr(e.X) // selection
   399  		} else {
   400  			return f.info.Uses[e.Sel].Type() // qualified identifier
   401  		}
   402  
   403  	case *ast.IndexExpr:
   404  		if instance(f.info, e.X) {
   405  			// f[T] or C[T] -- generic instantiation
   406  		} else {
   407  			// x[i] or m[k] -- index or lookup operation
   408  			x := f.expr(e.X)
   409  			i := f.expr(e.Index)
   410  			if ux, ok := coreType(x).(*types.Map); ok {
   411  				f.assign(ux.Key(), i)
   412  			}
   413  		}
   414  
   415  	case *typeparams.IndexListExpr:
   416  		// f[X, Y] -- generic instantiation
   417  
   418  	case *ast.SliceExpr:
   419  		f.expr(e.X)
   420  		if e.Low != nil {
   421  			f.expr(e.Low)
   422  		}
   423  		if e.High != nil {
   424  			f.expr(e.High)
   425  		}
   426  		if e.Max != nil {
   427  			f.expr(e.Max)
   428  		}
   429  
   430  	case *ast.TypeAssertExpr:
   431  		x := f.expr(e.X)
   432  		f.typeAssert(x, f.info.Types[e.Type].Type)
   433  
   434  	case *ast.CallExpr:
   435  		if tvFun := f.info.Types[e.Fun]; tvFun.IsType() {
   436  			// conversion
   437  			arg0 := f.expr(e.Args[0])
   438  			f.assign(tvFun.Type, arg0)
   439  		} else {
   440  			// function call
   441  
   442  			// unsafe call. Treat calls to functions in unsafe like ordinary calls,
   443  			// except that their signature cannot be determined by their func obj.
   444  			// Without this special handling, f.expr(e.Fun) would fail below.
   445  			if s, ok := unparen(e.Fun).(*ast.SelectorExpr); ok {
   446  				if obj, ok := f.info.Uses[s.Sel].(*types.Builtin); ok && obj.Pkg().Path() == "unsafe" {
   447  					sig := f.info.Types[e.Fun].Type.(*types.Signature)
   448  					f.call(sig, e.Args)
   449  					return tv.Type
   450  				}
   451  			}
   452  
   453  			// builtin call
   454  			if id, ok := unparen(e.Fun).(*ast.Ident); ok {
   455  				if obj, ok := f.info.Uses[id].(*types.Builtin); ok {
   456  					sig := f.info.Types[id].Type.(*types.Signature)
   457  					f.builtin(obj, sig, e.Args)
   458  					return tv.Type
   459  				}
   460  			}
   461  
   462  			// ordinary call
   463  			f.call(coreType(f.expr(e.Fun)).(*types.Signature), e.Args)
   464  		}
   465  
   466  	case *ast.StarExpr:
   467  		f.expr(e.X)
   468  
   469  	case *ast.UnaryExpr:
   470  		f.expr(e.X)
   471  
   472  	case *ast.BinaryExpr:
   473  		x := f.expr(e.X)
   474  		y := f.expr(e.Y)
   475  		if e.Op == token.EQL || e.Op == token.NEQ {
   476  			f.compare(x, y)
   477  		}
   478  
   479  	case *ast.KeyValueExpr:
   480  		f.expr(e.Key)
   481  		f.expr(e.Value)
   482  
   483  	case *ast.ArrayType,
   484  		*ast.StructType,
   485  		*ast.FuncType,
   486  		*ast.InterfaceType,
   487  		*ast.MapType,
   488  		*ast.ChanType:
   489  		panic(e)
   490  	}
   491  
   492  	if tv.Type == nil {
   493  		panic(fmt.Sprintf("no type for %T", e))
   494  	}
   495  
   496  	return tv.Type
   497  }
   498  
   499  func (f *Finder) stmt(s ast.Stmt) {
   500  	switch s := s.(type) {
   501  	case *ast.BadStmt,
   502  		*ast.EmptyStmt,
   503  		*ast.BranchStmt:
   504  		// no-op
   505  
   506  	case *ast.DeclStmt:
   507  		d := s.Decl.(*ast.GenDecl)
   508  		if d.Tok == token.VAR { // ignore consts
   509  			for _, spec := range d.Specs {
   510  				f.valueSpec(spec.(*ast.ValueSpec))
   511  			}
   512  		}
   513  
   514  	case *ast.LabeledStmt:
   515  		f.stmt(s.Stmt)
   516  
   517  	case *ast.ExprStmt:
   518  		f.expr(s.X)
   519  
   520  	case *ast.SendStmt:
   521  		ch := f.expr(s.Chan)
   522  		val := f.expr(s.Value)
   523  		f.assign(coreType(ch).(*types.Chan).Elem(), val)
   524  
   525  	case *ast.IncDecStmt:
   526  		f.expr(s.X)
   527  
   528  	case *ast.AssignStmt:
   529  		switch s.Tok {
   530  		case token.ASSIGN, token.DEFINE:
   531  			// y := x   or   y = x
   532  			var rhsTuple types.Type
   533  			if len(s.Lhs) != len(s.Rhs) {
   534  				rhsTuple = f.exprN(s.Rhs[0])
   535  			}
   536  			for i := range s.Lhs {
   537  				var lhs, rhs types.Type
   538  				if rhsTuple == nil {
   539  					rhs = f.expr(s.Rhs[i]) // 1:1 assignment
   540  				} else {
   541  					rhs = f.extract(rhsTuple, i) // n:1 assignment
   542  				}
   543  
   544  				if id, ok := s.Lhs[i].(*ast.Ident); ok {
   545  					if id.Name != "_" {
   546  						if obj, ok := f.info.Defs[id]; ok {
   547  							lhs = obj.Type() // definition
   548  						}
   549  					}
   550  				}
   551  				if lhs == nil {
   552  					lhs = f.expr(s.Lhs[i]) // assignment
   553  				}
   554  				f.assign(lhs, rhs)
   555  			}
   556  
   557  		default:
   558  			// y op= x
   559  			f.expr(s.Lhs[0])
   560  			f.expr(s.Rhs[0])
   561  		}
   562  
   563  	case *ast.GoStmt:
   564  		f.expr(s.Call)
   565  
   566  	case *ast.DeferStmt:
   567  		f.expr(s.Call)
   568  
   569  	case *ast.ReturnStmt:
   570  		formals := f.sig.Results()
   571  		switch len(s.Results) {
   572  		case formals.Len(): // 1:1
   573  			for i, result := range s.Results {
   574  				f.assign(formals.At(i).Type(), f.expr(result))
   575  			}
   576  
   577  		case 1: // n:1
   578  			tuple := f.exprN(s.Results[0])
   579  			for i := 0; i < formals.Len(); i++ {
   580  				f.assign(formals.At(i).Type(), f.extract(tuple, i))
   581  			}
   582  		}
   583  
   584  	case *ast.SelectStmt:
   585  		f.stmt(s.Body)
   586  
   587  	case *ast.BlockStmt:
   588  		for _, s := range s.List {
   589  			f.stmt(s)
   590  		}
   591  
   592  	case *ast.IfStmt:
   593  		if s.Init != nil {
   594  			f.stmt(s.Init)
   595  		}
   596  		f.expr(s.Cond)
   597  		f.stmt(s.Body)
   598  		if s.Else != nil {
   599  			f.stmt(s.Else)
   600  		}
   601  
   602  	case *ast.SwitchStmt:
   603  		if s.Init != nil {
   604  			f.stmt(s.Init)
   605  		}
   606  		var tag types.Type = tUntypedBool
   607  		if s.Tag != nil {
   608  			tag = f.expr(s.Tag)
   609  		}
   610  		for _, cc := range s.Body.List {
   611  			cc := cc.(*ast.CaseClause)
   612  			for _, cond := range cc.List {
   613  				f.compare(tag, f.info.Types[cond].Type)
   614  			}
   615  			for _, s := range cc.Body {
   616  				f.stmt(s)
   617  			}
   618  		}
   619  
   620  	case *ast.TypeSwitchStmt:
   621  		if s.Init != nil {
   622  			f.stmt(s.Init)
   623  		}
   624  		var I types.Type
   625  		switch ass := s.Assign.(type) {
   626  		case *ast.ExprStmt: // x.(type)
   627  			I = f.expr(unparen(ass.X).(*ast.TypeAssertExpr).X)
   628  		case *ast.AssignStmt: // y := x.(type)
   629  			I = f.expr(unparen(ass.Rhs[0]).(*ast.TypeAssertExpr).X)
   630  		}
   631  		for _, cc := range s.Body.List {
   632  			cc := cc.(*ast.CaseClause)
   633  			for _, cond := range cc.List {
   634  				tCase := f.info.Types[cond].Type
   635  				if tCase != tUntypedNil {
   636  					f.typeAssert(I, tCase)
   637  				}
   638  			}
   639  			for _, s := range cc.Body {
   640  				f.stmt(s)
   641  			}
   642  		}
   643  
   644  	case *ast.CommClause:
   645  		if s.Comm != nil {
   646  			f.stmt(s.Comm)
   647  		}
   648  		for _, s := range s.Body {
   649  			f.stmt(s)
   650  		}
   651  
   652  	case *ast.ForStmt:
   653  		if s.Init != nil {
   654  			f.stmt(s.Init)
   655  		}
   656  		if s.Cond != nil {
   657  			f.expr(s.Cond)
   658  		}
   659  		if s.Post != nil {
   660  			f.stmt(s.Post)
   661  		}
   662  		f.stmt(s.Body)
   663  
   664  	case *ast.RangeStmt:
   665  		x := f.expr(s.X)
   666  		// No conversions are involved when Tok==DEFINE.
   667  		if s.Tok == token.ASSIGN {
   668  			if s.Key != nil {
   669  				k := f.expr(s.Key)
   670  				var xelem types.Type
   671  				// Keys of array, *array, slice, string aren't interesting
   672  				// since the RHS key type is just an int.
   673  				switch ux := coreType(x).(type) {
   674  				case *types.Chan:
   675  					xelem = ux.Elem()
   676  				case *types.Map:
   677  					xelem = ux.Key()
   678  				}
   679  				if xelem != nil {
   680  					f.assign(k, xelem)
   681  				}
   682  			}
   683  			if s.Value != nil {
   684  				val := f.expr(s.Value)
   685  				var xelem types.Type
   686  				// Values of type strings aren't interesting because
   687  				// the RHS value type is just a rune.
   688  				switch ux := coreType(x).(type) {
   689  				case *types.Array:
   690  					xelem = ux.Elem()
   691  				case *types.Map:
   692  					xelem = ux.Elem()
   693  				case *types.Pointer: // *array
   694  					xelem = coreType(deref(ux)).(*types.Array).Elem()
   695  				case *types.Slice:
   696  					xelem = ux.Elem()
   697  				}
   698  				if xelem != nil {
   699  					f.assign(val, xelem)
   700  				}
   701  			}
   702  		}
   703  		f.stmt(s.Body)
   704  
   705  	default:
   706  		panic(s)
   707  	}
   708  }
   709  
   710  // -- Plundered from golang.org/x/tools/go/ssa -----------------
   711  
   712  // deref returns a pointer's element type; otherwise it returns typ.
   713  func deref(typ types.Type) types.Type {
   714  	if p, ok := coreType(typ).(*types.Pointer); ok {
   715  		return p.Elem()
   716  	}
   717  	return typ
   718  }
   719  
   720  func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
   721  
   722  func isInterface(T types.Type) bool { return types.IsInterface(T) }
   723  
   724  func coreType(T types.Type) types.Type { return typeparams.CoreType(T) }
   725  
   726  func instance(info *types.Info, expr ast.Expr) bool {
   727  	var id *ast.Ident
   728  	switch x := expr.(type) {
   729  	case *ast.Ident:
   730  		id = x
   731  	case *ast.SelectorExpr:
   732  		id = x.Sel
   733  	default:
   734  		return false
   735  	}
   736  	_, ok := typeparams.GetInstances(info)[id]
   737  	return ok
   738  }
   739  

View as plain text