github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/refactor/satisfy/find14.go (about)

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