golang.org/x/tools@v0.21.0/internal/refactor/inline/inline.go (about)

     1  // Copyright 2023 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 inline
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"go/ast"
    11  	"go/constant"
    12  	"go/format"
    13  	"go/parser"
    14  	"go/token"
    15  	"go/types"
    16  	pathpkg "path"
    17  	"reflect"
    18  	"strconv"
    19  	"strings"
    20  
    21  	"golang.org/x/tools/go/ast/astutil"
    22  	"golang.org/x/tools/go/types/typeutil"
    23  	"golang.org/x/tools/imports"
    24  	internalastutil "golang.org/x/tools/internal/astutil"
    25  	"golang.org/x/tools/internal/typeparams"
    26  )
    27  
    28  // A Caller describes the function call and its enclosing context.
    29  //
    30  // The client is responsible for populating this struct and passing it to Inline.
    31  type Caller struct {
    32  	Fset    *token.FileSet
    33  	Types   *types.Package
    34  	Info    *types.Info
    35  	File    *ast.File
    36  	Call    *ast.CallExpr
    37  	Content []byte // source of file containing
    38  
    39  	path          []ast.Node    // path from call to root of file syntax tree
    40  	enclosingFunc *ast.FuncDecl // top-level function/method enclosing the call, if any
    41  }
    42  
    43  // Options specifies parameters affecting the inliner algorithm.
    44  // All fields are optional.
    45  type Options struct {
    46  	Logf          func(string, ...any) // log output function, records decision-making process
    47  	IgnoreEffects bool                 // ignore potential side effects of arguments (unsound)
    48  }
    49  
    50  // Result holds the result of code transformation.
    51  type Result struct {
    52  	Content     []byte // formatted, transformed content of caller file
    53  	Literalized bool   // chosen strategy replaced callee() with func(){...}()
    54  
    55  	// TODO(adonovan): provide an API for clients that want structured
    56  	// output: a list of import additions and deletions plus one or more
    57  	// localized diffs (or even AST transformations, though ownership and
    58  	// mutation are tricky) near the call site.
    59  }
    60  
    61  // Inline inlines the called function (callee) into the function call (caller)
    62  // and returns the updated, formatted content of the caller source file.
    63  //
    64  // Inline does not mutate any public fields of Caller or Callee.
    65  func Inline(caller *Caller, callee *Callee, opts *Options) (*Result, error) {
    66  	copy := *opts // shallow copy
    67  	opts = &copy
    68  	// Set default options.
    69  	if opts.Logf == nil {
    70  		opts.Logf = func(string, ...any) {}
    71  	}
    72  
    73  	st := &state{
    74  		caller: caller,
    75  		callee: callee,
    76  		opts:   opts,
    77  	}
    78  	return st.inline()
    79  }
    80  
    81  // state holds the working state of the inliner.
    82  type state struct {
    83  	caller *Caller
    84  	callee *Callee
    85  	opts   *Options
    86  }
    87  
    88  func (st *state) inline() (*Result, error) {
    89  	logf, caller, callee := st.opts.Logf, st.caller, st.callee
    90  
    91  	logf("inline %s @ %v",
    92  		debugFormatNode(caller.Fset, caller.Call),
    93  		caller.Fset.PositionFor(caller.Call.Lparen, false))
    94  
    95  	if !consistentOffsets(caller) {
    96  		return nil, fmt.Errorf("internal error: caller syntax positions are inconsistent with file content (did you forget to use FileSet.PositionFor when computing the file name?)")
    97  	}
    98  
    99  	// TODO(adonovan): use go1.21's ast.IsGenerated.
   100  	// Break the string literal so we can use inlining in this file. :)
   101  	if bytes.Contains(caller.Content, []byte("// Code generated by "+"cmd/cgo; DO NOT EDIT.")) {
   102  		return nil, fmt.Errorf("cannot inline calls from files that import \"C\"")
   103  	}
   104  
   105  	res, err := st.inlineCall()
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  
   110  	// Replace the call (or some node that encloses it) by new syntax.
   111  	assert(res.old != nil, "old is nil")
   112  	assert(res.new != nil, "new is nil")
   113  
   114  	// A single return operand inlined to a unary
   115  	// expression context may need parens. Otherwise:
   116  	//    func two() int { return 1+1 }
   117  	//    print(-two())  =>  print(-1+1) // oops!
   118  	//
   119  	// Usually it is not necessary to insert ParenExprs
   120  	// as the formatter is smart enough to insert them as
   121  	// needed by the context. But the res.{old,new}
   122  	// substitution is done by formatting res.new in isolation
   123  	// and then splicing its text over res.old, so the
   124  	// formatter doesn't see the parent node and cannot do
   125  	// the right thing. (One solution would be to always
   126  	// format the enclosing node of old, but that requires
   127  	// non-lossy comment handling, #20744.)
   128  	//
   129  	// So, we must analyze the call's context
   130  	// to see whether ambiguity is possible.
   131  	// For example, if the context is x[y:z], then
   132  	// the x subtree is subject to precedence ambiguity
   133  	// (replacing x by p+q would give p+q[y:z] which is wrong)
   134  	// but the y and z subtrees are safe.
   135  	if needsParens(caller.path, res.old, res.new) {
   136  		res.new = &ast.ParenExpr{X: res.new.(ast.Expr)}
   137  	}
   138  
   139  	// Some reduction strategies return a new block holding the
   140  	// callee's statements. The block's braces may be elided when
   141  	// there is no conflict between names declared in the block
   142  	// with those declared by the parent block, and no risk of
   143  	// a caller's goto jumping forward across a declaration.
   144  	//
   145  	// This elision is only safe when the ExprStmt is beneath a
   146  	// BlockStmt, CaseClause.Body, or CommClause.Body;
   147  	// (see "statement theory").
   148  	//
   149  	// The inlining analysis may have already determined that eliding braces is
   150  	// safe. Otherwise, we analyze its safety here.
   151  	elideBraces := res.elideBraces
   152  	if !elideBraces {
   153  		if newBlock, ok := res.new.(*ast.BlockStmt); ok {
   154  			i := nodeIndex(caller.path, res.old)
   155  			parent := caller.path[i+1]
   156  			var body []ast.Stmt
   157  			switch parent := parent.(type) {
   158  			case *ast.BlockStmt:
   159  				body = parent.List
   160  			case *ast.CommClause:
   161  				body = parent.Body
   162  			case *ast.CaseClause:
   163  				body = parent.Body
   164  			}
   165  			if body != nil {
   166  				callerNames := declares(body)
   167  
   168  				// If BlockStmt is a function body,
   169  				// include its receiver, params, and results.
   170  				addFieldNames := func(fields *ast.FieldList) {
   171  					if fields != nil {
   172  						for _, field := range fields.List {
   173  							for _, id := range field.Names {
   174  								callerNames[id.Name] = true
   175  							}
   176  						}
   177  					}
   178  				}
   179  				switch f := caller.path[i+2].(type) {
   180  				case *ast.FuncDecl:
   181  					addFieldNames(f.Recv)
   182  					addFieldNames(f.Type.Params)
   183  					addFieldNames(f.Type.Results)
   184  				case *ast.FuncLit:
   185  					addFieldNames(f.Type.Params)
   186  					addFieldNames(f.Type.Results)
   187  				}
   188  
   189  				if len(callerLabels(caller.path)) > 0 {
   190  					// TODO(adonovan): be more precise and reject
   191  					// only forward gotos across the inlined block.
   192  					logf("keeping block braces: caller uses control labels")
   193  				} else if intersects(declares(newBlock.List), callerNames) {
   194  					logf("keeping block braces: avoids name conflict")
   195  				} else {
   196  					elideBraces = true
   197  				}
   198  			}
   199  		}
   200  	}
   201  
   202  	// Don't call replaceNode(caller.File, res.old, res.new)
   203  	// as it mutates the caller's syntax tree.
   204  	// Instead, splice the file, replacing the extent of the "old"
   205  	// node by a formatting of the "new" node, and re-parse.
   206  	// We'll fix up the imports on this new tree, and format again.
   207  	var f *ast.File
   208  	{
   209  		start := offsetOf(caller.Fset, res.old.Pos())
   210  		end := offsetOf(caller.Fset, res.old.End())
   211  		var out bytes.Buffer
   212  		out.Write(caller.Content[:start])
   213  		// TODO(adonovan): might it make more sense to use
   214  		// callee.Fset when formatting res.new?
   215  		// The new tree is a mix of (cloned) caller nodes for
   216  		// the argument expressions and callee nodes for the
   217  		// function body. In essence the question is: which
   218  		// is more likely to have comments?
   219  		// Usually the callee body will be larger and more
   220  		// statement-heavy than the arguments, but a
   221  		// strategy may widen the scope of the replacement
   222  		// (res.old) from CallExpr to, say, its enclosing
   223  		// block, so the caller nodes dominate.
   224  		// Precise comment handling would make this a
   225  		// non-issue. Formatting wouldn't really need a
   226  		// FileSet at all.
   227  		if elideBraces {
   228  			for i, stmt := range res.new.(*ast.BlockStmt).List {
   229  				if i > 0 {
   230  					out.WriteByte('\n')
   231  				}
   232  				if err := format.Node(&out, caller.Fset, stmt); err != nil {
   233  					return nil, err
   234  				}
   235  			}
   236  		} else {
   237  			if err := format.Node(&out, caller.Fset, res.new); err != nil {
   238  				return nil, err
   239  			}
   240  		}
   241  		out.Write(caller.Content[end:])
   242  		const mode = parser.ParseComments | parser.SkipObjectResolution | parser.AllErrors
   243  		f, err = parser.ParseFile(caller.Fset, "callee.go", &out, mode)
   244  		if err != nil {
   245  			// Something has gone very wrong.
   246  			logf("failed to parse <<%s>>", &out) // debugging
   247  			return nil, err
   248  		}
   249  	}
   250  
   251  	// Add new imports.
   252  	//
   253  	// Insert new imports after last existing import,
   254  	// to avoid migration of pre-import comments.
   255  	// The imports will be organized below.
   256  	if len(res.newImports) > 0 {
   257  		var importDecl *ast.GenDecl
   258  		if len(f.Imports) > 0 {
   259  			// Append specs to existing import decl
   260  			importDecl = f.Decls[0].(*ast.GenDecl)
   261  		} else {
   262  			// Insert new import decl.
   263  			importDecl = &ast.GenDecl{Tok: token.IMPORT}
   264  			f.Decls = prepend[ast.Decl](importDecl, f.Decls...)
   265  		}
   266  		for _, imp := range res.newImports {
   267  			// Check that the new imports are accessible.
   268  			path, _ := strconv.Unquote(imp.spec.Path.Value)
   269  			if !canImport(caller.Types.Path(), path) {
   270  				return nil, fmt.Errorf("can't inline function %v as its body refers to inaccessible package %q", callee, path)
   271  			}
   272  			importDecl.Specs = append(importDecl.Specs, imp.spec)
   273  		}
   274  	}
   275  
   276  	var out bytes.Buffer
   277  	if err := format.Node(&out, caller.Fset, f); err != nil {
   278  		return nil, err
   279  	}
   280  	newSrc := out.Bytes()
   281  
   282  	// Remove imports that are no longer referenced.
   283  	//
   284  	// It ought to be possible to compute the set of PkgNames used
   285  	// by the "old" code, compute the free identifiers of the
   286  	// "new" code using a syntax-only (no go/types) algorithm, and
   287  	// see if the reduction in the number of uses of any PkgName
   288  	// equals the number of times it appears in caller.Info.Uses,
   289  	// indicating that it is no longer referenced by res.new.
   290  	//
   291  	// However, the notorious ambiguity of resolving T{F: 0} makes this
   292  	// unreliable: without types, we can't tell whether F refers to
   293  	// a field of struct T, or a package-level const/var of a
   294  	// dot-imported (!) package.
   295  	//
   296  	// So, for now, we run imports.Process, which is
   297  	// unsatisfactory as it has to run the go command, and it
   298  	// looks at the user's module cache state--unnecessarily,
   299  	// since this step cannot add new imports.
   300  	//
   301  	// TODO(adonovan): replace with a simpler implementation since
   302  	// all the necessary imports are present but merely untidy.
   303  	// That will be faster, and also less prone to nondeterminism
   304  	// if there are bugs in our logic for import maintenance.
   305  	//
   306  	// However, golang.org/x/tools/internal/imports.ApplyFixes is
   307  	// too simple as it requires the caller to have figured out
   308  	// all the logical edits. In our case, we know all the new
   309  	// imports that are needed (see newImports), each of which can
   310  	// be specified as:
   311  	//
   312  	//   &imports.ImportFix{
   313  	//     StmtInfo: imports.ImportInfo{path, name,
   314  	//     IdentName: name,
   315  	//     FixType:   imports.AddImport,
   316  	//   }
   317  	//
   318  	// but we don't know which imports are made redundant by the
   319  	// inlining itself. For example, inlining a call to
   320  	// fmt.Println may make the "fmt" import redundant.
   321  	//
   322  	// Also, both imports.Process and internal/imports.ApplyFixes
   323  	// reformat the entire file, which is not ideal for clients
   324  	// such as gopls. (That said, the point of a canonical format
   325  	// is arguably that any tool can reformat as needed without
   326  	// this being inconvenient.)
   327  	//
   328  	// We could invoke imports.Process and parse its result,
   329  	// compare against the original AST, compute a list of import
   330  	// fixes, and return that too.
   331  
   332  	// Recompute imports only if there were existing ones.
   333  	if len(f.Imports) > 0 {
   334  		formatted, err := imports.Process("output", newSrc, nil)
   335  		if err != nil {
   336  			logf("cannot reformat: %v <<%s>>", err, &out)
   337  			return nil, err // cannot reformat (a bug?)
   338  		}
   339  		newSrc = formatted
   340  	}
   341  
   342  	literalized := false
   343  	if call, ok := res.new.(*ast.CallExpr); ok && is[*ast.FuncLit](call.Fun) {
   344  		literalized = true
   345  	}
   346  
   347  	return &Result{
   348  		Content:     newSrc,
   349  		Literalized: literalized,
   350  	}, nil
   351  
   352  }
   353  
   354  type newImport struct {
   355  	pkgName string
   356  	spec    *ast.ImportSpec
   357  }
   358  
   359  type inlineCallResult struct {
   360  	newImports []newImport
   361  	// If elideBraces is set, old is an ast.Stmt and new is an ast.BlockStmt to
   362  	// be spliced in. This allows the inlining analysis to assert that inlining
   363  	// the block is OK; if elideBraces is unset and old is an ast.Stmt and new is
   364  	// an ast.BlockStmt, braces may still be elided if the post-processing
   365  	// analysis determines that it is safe to do so.
   366  	//
   367  	// Ideally, it would not be necessary for the inlining analysis to "reach
   368  	// through" to the post-processing pass in this way. Instead, inlining could
   369  	// just set old to be an ast.BlockStmt and rewrite the entire BlockStmt, but
   370  	// unfortunately in order to preserve comments, it is important that inlining
   371  	// replace as little syntax as possible.
   372  	elideBraces bool
   373  	old, new    ast.Node // e.g. replace call expr by callee function body expression
   374  }
   375  
   376  // inlineCall returns a pair of an old node (the call, or something
   377  // enclosing it) and a new node (its replacement, which may be a
   378  // combination of caller, callee, and new nodes), along with the set
   379  // of new imports needed.
   380  //
   381  // TODO(adonovan): rethink the 'result' interface. The assumption of a
   382  // one-to-one replacement seems fragile. One can easily imagine the
   383  // transformation replacing the call and adding new variable
   384  // declarations, for example, or replacing a call statement by zero or
   385  // many statements.)
   386  //
   387  // TODO(adonovan): in earlier drafts, the transformation was expressed
   388  // by splicing substrings of the two source files because syntax
   389  // trees don't preserve comments faithfully (see #20744), but such
   390  // transformations don't compose. The current implementation is
   391  // tree-based but is very lossy wrt comments. It would make a good
   392  // candidate for evaluating an alternative fully self-contained tree
   393  // representation, such as any proposed solution to #20744, or even
   394  // dst or some private fork of go/ast.)
   395  func (st *state) inlineCall() (*inlineCallResult, error) {
   396  	logf, caller, callee := st.opts.Logf, st.caller, &st.callee.impl
   397  
   398  	checkInfoFields(caller.Info)
   399  
   400  	// Inlining of dynamic calls is not currently supported,
   401  	// even for local closure calls. (This would be a lot of work.)
   402  	calleeSymbol := typeutil.StaticCallee(caller.Info, caller.Call)
   403  	if calleeSymbol == nil {
   404  		// e.g. interface method
   405  		return nil, fmt.Errorf("cannot inline: not a static function call")
   406  	}
   407  
   408  	// Reject cross-package inlining if callee has
   409  	// free references to unexported symbols.
   410  	samePkg := caller.Types.Path() == callee.PkgPath
   411  	if !samePkg && len(callee.Unexported) > 0 {
   412  		return nil, fmt.Errorf("cannot inline call to %s because body refers to non-exported %s",
   413  			callee.Name, callee.Unexported[0])
   414  	}
   415  
   416  	// -- analyze callee's free references in caller context --
   417  
   418  	// Compute syntax path enclosing Call, innermost first (Path[0]=Call),
   419  	// and outermost enclosing function, if any.
   420  	caller.path, _ = astutil.PathEnclosingInterval(caller.File, caller.Call.Pos(), caller.Call.End())
   421  	for _, n := range caller.path {
   422  		if decl, ok := n.(*ast.FuncDecl); ok {
   423  			caller.enclosingFunc = decl
   424  			break
   425  		}
   426  	}
   427  
   428  	// If call is within a function, analyze all its
   429  	// local vars for the "single assignment" property.
   430  	// (Taking the address &v counts as a potential assignment.)
   431  	var assign1 func(v *types.Var) bool // reports whether v a single-assignment local var
   432  	{
   433  		updatedLocals := make(map[*types.Var]bool)
   434  		if caller.enclosingFunc != nil {
   435  			escape(caller.Info, caller.enclosingFunc, func(v *types.Var, _ bool) {
   436  				updatedLocals[v] = true
   437  			})
   438  			logf("multiple-assignment vars: %v", updatedLocals)
   439  		}
   440  		assign1 = func(v *types.Var) bool { return !updatedLocals[v] }
   441  	}
   442  
   443  	// import map, initially populated with caller imports.
   444  	//
   445  	// For simplicity we ignore existing dot imports, so that a
   446  	// qualified identifier (QI) in the callee is always
   447  	// represented by a QI in the caller, allowing us to treat a
   448  	// QI like a selection on a package name.
   449  	importMap := make(map[string][]string) // maps package path to local name(s)
   450  	for _, imp := range caller.File.Imports {
   451  		if pkgname, ok := importedPkgName(caller.Info, imp); ok &&
   452  			pkgname.Name() != "." &&
   453  			pkgname.Name() != "_" {
   454  			path := pkgname.Imported().Path()
   455  			importMap[path] = append(importMap[path], pkgname.Name())
   456  		}
   457  	}
   458  
   459  	// localImportName returns the local name for a given imported package path.
   460  	var newImports []newImport
   461  	localImportName := func(obj *object) string {
   462  		// Does an import exist?
   463  		for _, name := range importMap[obj.PkgPath] {
   464  			// Check that either the import preexisted,
   465  			// or that it was newly added (no PkgName) but is not shadowed,
   466  			// either in the callee (shadows) or caller (caller.lookup).
   467  			if !obj.Shadow[name] {
   468  				found := caller.lookup(name)
   469  				if is[*types.PkgName](found) || found == nil {
   470  					return name
   471  				}
   472  			}
   473  		}
   474  
   475  		newlyAdded := func(name string) bool {
   476  			for _, new := range newImports {
   477  				if new.pkgName == name {
   478  					return true
   479  				}
   480  			}
   481  			return false
   482  		}
   483  
   484  		// import added by callee
   485  		//
   486  		// Choose local PkgName based on last segment of
   487  		// package path plus, if needed, a numeric suffix to
   488  		// ensure uniqueness.
   489  		//
   490  		// "init" is not a legal PkgName.
   491  		//
   492  		// TODO(rfindley): is it worth preserving local package names for callee
   493  		// imports? Are they likely to be better or worse than the name we choose
   494  		// here?
   495  		base := obj.PkgName
   496  		name := base
   497  		for n := 0; obj.Shadow[name] || caller.lookup(name) != nil || newlyAdded(name) || name == "init"; n++ {
   498  			name = fmt.Sprintf("%s%d", base, n)
   499  		}
   500  
   501  		logf("adding import %s %q", name, obj.PkgPath)
   502  		spec := &ast.ImportSpec{
   503  			Path: &ast.BasicLit{
   504  				Kind:  token.STRING,
   505  				Value: strconv.Quote(obj.PkgPath),
   506  			},
   507  		}
   508  		// Use explicit pkgname (out of necessity) when it differs from the declared name,
   509  		// or (for good style) when it differs from base(pkgpath).
   510  		if name != obj.PkgName || name != pathpkg.Base(obj.PkgPath) {
   511  			spec.Name = makeIdent(name)
   512  		}
   513  		newImports = append(newImports, newImport{
   514  			pkgName: name,
   515  			spec:    spec,
   516  		})
   517  		importMap[obj.PkgPath] = append(importMap[obj.PkgPath], name)
   518  		return name
   519  	}
   520  
   521  	// Compute the renaming of the callee's free identifiers.
   522  	objRenames := make([]ast.Expr, len(callee.FreeObjs)) // nil => no change
   523  	for i, obj := range callee.FreeObjs {
   524  		// obj is a free object of the callee.
   525  		//
   526  		// Possible cases are:
   527  		// - builtin function, type, or value (e.g. nil, zero)
   528  		//   => check not shadowed in caller.
   529  		// - package-level var/func/const/types
   530  		//   => same package: check not shadowed in caller.
   531  		//   => otherwise: import other package, form a qualified identifier.
   532  		//      (Unexported cross-package references were rejected already.)
   533  		// - type parameter
   534  		//   => not yet supported
   535  		// - pkgname
   536  		//   => import other package and use its local name.
   537  		//
   538  		// There can be no free references to labels, fields, or methods.
   539  
   540  		// Note that we must consider potential shadowing both
   541  		// at the caller side (caller.lookup) and, when
   542  		// choosing new PkgNames, within the callee (obj.shadow).
   543  
   544  		var newName ast.Expr
   545  		if obj.Kind == "pkgname" {
   546  			// Use locally appropriate import, creating as needed.
   547  			newName = makeIdent(localImportName(&obj)) // imported package
   548  		} else if !obj.ValidPos {
   549  			// Built-in function, type, or value (e.g. nil, zero):
   550  			// check not shadowed at caller.
   551  			found := caller.lookup(obj.Name) // always finds something
   552  			if found.Pos().IsValid() {
   553  				return nil, fmt.Errorf("cannot inline, because the callee refers to built-in %q, which in the caller is shadowed by a %s (declared at line %d)",
   554  					obj.Name, objectKind(found),
   555  					caller.Fset.PositionFor(found.Pos(), false).Line)
   556  			}
   557  
   558  		} else {
   559  			// Must be reference to package-level var/func/const/type,
   560  			// since type parameters are not yet supported.
   561  			qualify := false
   562  			if obj.PkgPath == callee.PkgPath {
   563  				// reference within callee package
   564  				if samePkg {
   565  					// Caller and callee are in same package.
   566  					// Check caller has not shadowed the decl.
   567  					//
   568  					// This may fail if the callee is "fake", such as for signature
   569  					// refactoring where the callee is modified to be a trivial wrapper
   570  					// around the refactored signature.
   571  					found := caller.lookup(obj.Name)
   572  					if found != nil && !isPkgLevel(found) {
   573  						return nil, fmt.Errorf("cannot inline, because the callee refers to %s %q, which in the caller is shadowed by a %s (declared at line %d)",
   574  							obj.Kind, obj.Name,
   575  							objectKind(found),
   576  							caller.Fset.PositionFor(found.Pos(), false).Line)
   577  					}
   578  				} else {
   579  					// Cross-package reference.
   580  					qualify = true
   581  				}
   582  			} else {
   583  				// Reference to a package-level declaration
   584  				// in another package, without a qualified identifier:
   585  				// it must be a dot import.
   586  				qualify = true
   587  			}
   588  
   589  			// Form a qualified identifier, pkg.Name.
   590  			if qualify {
   591  				pkgName := localImportName(&obj)
   592  				newName = &ast.SelectorExpr{
   593  					X:   makeIdent(pkgName),
   594  					Sel: makeIdent(obj.Name),
   595  				}
   596  			}
   597  		}
   598  		objRenames[i] = newName
   599  	}
   600  
   601  	res := &inlineCallResult{
   602  		newImports: newImports,
   603  	}
   604  
   605  	// Parse callee function declaration.
   606  	calleeFset, calleeDecl, err := parseCompact(callee.Content)
   607  	if err != nil {
   608  		return nil, err // "can't happen"
   609  	}
   610  
   611  	// replaceCalleeID replaces an identifier in the callee.
   612  	// The replacement tree must not belong to the caller; use cloneNode as needed.
   613  	replaceCalleeID := func(offset int, repl ast.Expr) {
   614  		id := findIdent(calleeDecl, calleeDecl.Pos()+token.Pos(offset))
   615  		logf("- replace id %q @ #%d to %q", id.Name, offset, debugFormatNode(calleeFset, repl))
   616  		replaceNode(calleeDecl, id, repl)
   617  	}
   618  
   619  	// Generate replacements for each free identifier.
   620  	// (The same tree may be spliced in multiple times, resulting in a DAG.)
   621  	for _, ref := range callee.FreeRefs {
   622  		if repl := objRenames[ref.Object]; repl != nil {
   623  			replaceCalleeID(ref.Offset, repl)
   624  		}
   625  	}
   626  
   627  	// Gather the effective call arguments, including the receiver.
   628  	// Later, elements will be eliminated (=> nil) by parameter substitution.
   629  	args, err := st.arguments(caller, calleeDecl, assign1)
   630  	if err != nil {
   631  		return nil, err // e.g. implicit field selection cannot be made explicit
   632  	}
   633  
   634  	// Gather effective parameter tuple, including the receiver if any.
   635  	// Simplify variadic parameters to slices (in all cases but one).
   636  	var params []*parameter // including receiver; nil => parameter substituted
   637  	{
   638  		sig := calleeSymbol.Type().(*types.Signature)
   639  		if sig.Recv() != nil {
   640  			params = append(params, &parameter{
   641  				obj:       sig.Recv(),
   642  				fieldType: calleeDecl.Recv.List[0].Type,
   643  				info:      callee.Params[0],
   644  			})
   645  		}
   646  
   647  		// Flatten the list of syntactic types.
   648  		var types []ast.Expr
   649  		for _, field := range calleeDecl.Type.Params.List {
   650  			if field.Names == nil {
   651  				types = append(types, field.Type)
   652  			} else {
   653  				for range field.Names {
   654  					types = append(types, field.Type)
   655  				}
   656  			}
   657  		}
   658  
   659  		for i := 0; i < sig.Params().Len(); i++ {
   660  			params = append(params, &parameter{
   661  				obj:       sig.Params().At(i),
   662  				fieldType: types[i],
   663  				info:      callee.Params[len(params)],
   664  			})
   665  		}
   666  
   667  		// Variadic function?
   668  		//
   669  		// There are three possible types of call:
   670  		// - ordinary f(a1, ..., aN)
   671  		// - ellipsis f(a1, ..., slice...)
   672  		// - spread   f(recv?, g()) where g() is a tuple.
   673  		// The first two are desugared to non-variadic calls
   674  		// with an ordinary slice parameter;
   675  		// the third is tricky and cannot be reduced, and (if
   676  		// a receiver is present) cannot even be literalized.
   677  		// Fortunately it is vanishingly rare.
   678  		//
   679  		// TODO(adonovan): extract this to a function.
   680  		if sig.Variadic() {
   681  			lastParam := last(params)
   682  			if len(args) > 0 && last(args).spread {
   683  				// spread call to variadic: tricky
   684  				lastParam.variadic = true
   685  			} else {
   686  				// ordinary/ellipsis call to variadic
   687  
   688  				// simplify decl: func(T...) -> func([]T)
   689  				lastParamField := last(calleeDecl.Type.Params.List)
   690  				lastParamField.Type = &ast.ArrayType{
   691  					Elt: lastParamField.Type.(*ast.Ellipsis).Elt,
   692  				}
   693  
   694  				if caller.Call.Ellipsis.IsValid() {
   695  					// ellipsis call: f(slice...) -> f(slice)
   696  					// nop
   697  				} else {
   698  					// ordinary call: f(a1, ... aN) -> f([]T{a1, ..., aN})
   699  					n := len(params) - 1
   700  					ordinary, extra := args[:n], args[n:]
   701  					var elts []ast.Expr
   702  					pure, effects := true, false
   703  					for _, arg := range extra {
   704  						elts = append(elts, arg.expr)
   705  						pure = pure && arg.pure
   706  						effects = effects || arg.effects
   707  					}
   708  					args = append(ordinary, &argument{
   709  						expr: &ast.CompositeLit{
   710  							Type: lastParamField.Type,
   711  							Elts: elts,
   712  						},
   713  						typ:        lastParam.obj.Type(),
   714  						constant:   nil,
   715  						pure:       pure,
   716  						effects:    effects,
   717  						duplicable: false,
   718  						freevars:   nil, // not needed
   719  					})
   720  				}
   721  			}
   722  		}
   723  	}
   724  
   725  	// Log effective arguments.
   726  	for i, arg := range args {
   727  		logf("arg #%d: %s pure=%t effects=%t duplicable=%t free=%v type=%v",
   728  			i, debugFormatNode(caller.Fset, arg.expr),
   729  			arg.pure, arg.effects, arg.duplicable, arg.freevars, arg.typ)
   730  	}
   731  
   732  	// Note: computation below should be expressed in terms of
   733  	// the args and params slices, not the raw material.
   734  
   735  	// Perform parameter substitution.
   736  	// May eliminate some elements of params/args.
   737  	substitute(logf, caller, params, args, callee.Effects, callee.Falcon, replaceCalleeID)
   738  
   739  	// Update the callee's signature syntax.
   740  	updateCalleeParams(calleeDecl, params)
   741  
   742  	// Create a var (param = arg; ...) decl for use by some strategies.
   743  	bindingDecl := createBindingDecl(logf, caller, args, calleeDecl, callee.Results)
   744  
   745  	var remainingArgs []ast.Expr
   746  	for _, arg := range args {
   747  		if arg != nil {
   748  			remainingArgs = append(remainingArgs, arg.expr)
   749  		}
   750  	}
   751  
   752  	// -- let the inlining strategies begin --
   753  	//
   754  	// When we commit to a strategy, we log a message of the form:
   755  	//
   756  	//   "strategy: reduce expr-context call to { return expr }"
   757  	//
   758  	// This is a terse way of saying:
   759  	//
   760  	//    we plan to reduce a call
   761  	//    that appears in expression context
   762  	//    to a function whose body is of the form { return expr }
   763  
   764  	// TODO(adonovan): split this huge function into a sequence of
   765  	// function calls with an error sentinel that means "try the
   766  	// next strategy", and make sure each strategy writes to the
   767  	// log the reason it didn't match.
   768  
   769  	// Special case: eliminate a call to a function whose body is empty.
   770  	// (=> callee has no results and caller is a statement.)
   771  	//
   772  	//    func f(params) {}
   773  	//    f(args)
   774  	//    => _, _ = args
   775  	//
   776  	if len(calleeDecl.Body.List) == 0 {
   777  		logf("strategy: reduce call to empty body")
   778  
   779  		// Evaluate the arguments for effects and delete the call entirely.
   780  		stmt := callStmt(caller.path, false) // cannot fail
   781  		res.old = stmt
   782  		if nargs := len(remainingArgs); nargs > 0 {
   783  			// Emit "_, _ = args" to discard results.
   784  
   785  			// TODO(adonovan): if args is the []T{a1, ..., an}
   786  			// literal synthesized during variadic simplification,
   787  			// consider unwrapping it to its (pure) elements.
   788  			// Perhaps there's no harm doing this for any slice literal.
   789  
   790  			// Make correction for spread calls
   791  			// f(g()) or recv.f(g()) where g() is a tuple.
   792  			if last := last(args); last != nil && last.spread {
   793  				nspread := last.typ.(*types.Tuple).Len()
   794  				if len(args) > 1 { // [recv, g()]
   795  					// A single AssignStmt cannot discard both, so use a 2-spec var decl.
   796  					res.new = &ast.GenDecl{
   797  						Tok: token.VAR,
   798  						Specs: []ast.Spec{
   799  							&ast.ValueSpec{
   800  								Names:  []*ast.Ident{makeIdent("_")},
   801  								Values: []ast.Expr{args[0].expr},
   802  							},
   803  							&ast.ValueSpec{
   804  								Names:  blanks[*ast.Ident](nspread),
   805  								Values: []ast.Expr{args[1].expr},
   806  							},
   807  						},
   808  					}
   809  					return res, nil
   810  				}
   811  
   812  				// Sole argument is spread call.
   813  				nargs = nspread
   814  			}
   815  
   816  			res.new = &ast.AssignStmt{
   817  				Lhs: blanks[ast.Expr](nargs),
   818  				Tok: token.ASSIGN,
   819  				Rhs: remainingArgs,
   820  			}
   821  
   822  		} else {
   823  			// No remaining arguments: delete call statement entirely
   824  			res.new = &ast.EmptyStmt{}
   825  		}
   826  		return res, nil
   827  	}
   828  
   829  	// If all parameters have been substituted and no result
   830  	// variable is referenced, we don't need a binding decl.
   831  	// This may enable better reduction strategies.
   832  	allResultsUnreferenced := forall(callee.Results, func(i int, r *paramInfo) bool { return len(r.Refs) == 0 })
   833  	needBindingDecl := !allResultsUnreferenced ||
   834  		exists(params, func(i int, p *parameter) bool { return p != nil })
   835  
   836  	// The two strategies below overlap for a tail call of {return exprs}:
   837  	// The expr-context reduction is nice because it keeps the
   838  	// caller's return stmt and merely switches its operand,
   839  	// without introducing a new block, but it doesn't work with
   840  	// implicit return conversions.
   841  	//
   842  	// TODO(adonovan): unify these cases more cleanly, allowing return-
   843  	// operand replacement and implicit conversions, by adding
   844  	// conversions around each return operand (if not a spread return).
   845  
   846  	// Special case: call to { return exprs }.
   847  	//
   848  	// Reduces to:
   849  	//	    { var (bindings); _, _ = exprs }
   850  	//     or   _, _ = exprs
   851  	//     or   expr
   852  	//
   853  	// If:
   854  	// - the body is just "return expr" with trivial implicit conversions,
   855  	//   or the caller's return type matches the callee's,
   856  	// - all parameters and result vars can be eliminated
   857  	//   or replaced by a binding decl,
   858  	// then the call expression can be replaced by the
   859  	// callee's body expression, suitably substituted.
   860  	if len(calleeDecl.Body.List) == 1 &&
   861  		is[*ast.ReturnStmt](calleeDecl.Body.List[0]) &&
   862  		len(calleeDecl.Body.List[0].(*ast.ReturnStmt).Results) > 0 { // not a bare return
   863  		results := calleeDecl.Body.List[0].(*ast.ReturnStmt).Results
   864  
   865  		parent, grandparent := callContext(caller.path)
   866  
   867  		// statement context
   868  		if stmt, ok := parent.(*ast.ExprStmt); ok &&
   869  			(!needBindingDecl || bindingDecl != nil) {
   870  			logf("strategy: reduce stmt-context call to { return exprs }")
   871  			clearPositions(calleeDecl.Body)
   872  
   873  			if callee.ValidForCallStmt {
   874  				logf("callee body is valid as statement")
   875  				// Inv: len(results) == 1
   876  				if !needBindingDecl {
   877  					// Reduces to: expr
   878  					res.old = caller.Call
   879  					res.new = results[0]
   880  				} else {
   881  					// Reduces to: { var (bindings); expr }
   882  					res.old = stmt
   883  					res.new = &ast.BlockStmt{
   884  						List: []ast.Stmt{
   885  							bindingDecl.stmt,
   886  							&ast.ExprStmt{X: results[0]},
   887  						},
   888  					}
   889  				}
   890  			} else {
   891  				logf("callee body is not valid as statement")
   892  				// The call is a standalone statement, but the
   893  				// callee body is not suitable as a standalone statement
   894  				// (f() or <-ch), explicitly discard the results:
   895  				// Reduces to: _, _ = exprs
   896  				discard := &ast.AssignStmt{
   897  					Lhs: blanks[ast.Expr](callee.NumResults),
   898  					Tok: token.ASSIGN,
   899  					Rhs: results,
   900  				}
   901  				res.old = stmt
   902  				if !needBindingDecl {
   903  					// Reduces to: _, _ = exprs
   904  					res.new = discard
   905  				} else {
   906  					// Reduces to: { var (bindings); _, _ = exprs }
   907  					res.new = &ast.BlockStmt{
   908  						List: []ast.Stmt{
   909  							bindingDecl.stmt,
   910  							discard,
   911  						},
   912  					}
   913  				}
   914  			}
   915  			return res, nil
   916  		}
   917  
   918  		// Assignment context.
   919  		//
   920  		// If there is no binding decl, or if the binding decl declares no names,
   921  		// an assignment a, b := f() can be reduced to a, b := x, y.
   922  		if stmt, ok := parent.(*ast.AssignStmt); ok &&
   923  			is[*ast.BlockStmt](grandparent) &&
   924  			(!needBindingDecl || (bindingDecl != nil && len(bindingDecl.names) == 0)) {
   925  
   926  			// Reduces to: { var (bindings); lhs... := rhs... }
   927  			if newStmts, ok := st.assignStmts(stmt, results); ok {
   928  				logf("strategy: reduce assign-context call to { return exprs }")
   929  				clearPositions(calleeDecl.Body)
   930  
   931  				block := &ast.BlockStmt{
   932  					List: newStmts,
   933  				}
   934  				if needBindingDecl {
   935  					block.List = prepend(bindingDecl.stmt, block.List...)
   936  				}
   937  
   938  				// assignStmts does not introduce new bindings, and replacing an
   939  				// assignment only works if the replacement occurs in the same scope.
   940  				// Therefore, we must ensure that braces are elided.
   941  				res.elideBraces = true
   942  				res.old = stmt
   943  				res.new = block
   944  				return res, nil
   945  			}
   946  		}
   947  
   948  		// expression context
   949  		if !needBindingDecl {
   950  			clearPositions(calleeDecl.Body)
   951  
   952  			anyNonTrivialReturns := hasNonTrivialReturn(callee.Returns)
   953  
   954  			if callee.NumResults == 1 {
   955  				logf("strategy: reduce expr-context call to { return expr }")
   956  				// (includes some simple tail-calls)
   957  
   958  				// Make implicit return conversion explicit.
   959  				if anyNonTrivialReturns {
   960  					results[0] = convert(calleeDecl.Type.Results.List[0].Type, results[0])
   961  				}
   962  
   963  				res.old = caller.Call
   964  				res.new = results[0]
   965  				return res, nil
   966  
   967  			} else if !anyNonTrivialReturns {
   968  				logf("strategy: reduce spread-context call to { return expr }")
   969  				// There is no general way to reify conversions in a spread
   970  				// return, hence the requirement above.
   971  				//
   972  				// TODO(adonovan): allow this reduction when no
   973  				// conversion is required by the context.
   974  
   975  				// The call returns multiple results but is
   976  				// not a standalone call statement. It must
   977  				// be the RHS of a spread assignment:
   978  				//   var x, y  = f()
   979  				//       x, y := f()
   980  				//       x, y  = f()
   981  				// or the sole argument to a spread call:
   982  				//        printf(f())
   983  				// or spread return statement:
   984  				//        return f()
   985  				res.old = parent
   986  				switch context := parent.(type) {
   987  				case *ast.AssignStmt:
   988  					// Inv: the call must be in Rhs[0], not Lhs.
   989  					assign := shallowCopy(context)
   990  					assign.Rhs = results
   991  					res.new = assign
   992  				case *ast.ValueSpec:
   993  					// Inv: the call must be in Values[0], not Names.
   994  					spec := shallowCopy(context)
   995  					spec.Values = results
   996  					res.new = spec
   997  				case *ast.CallExpr:
   998  					// Inv: the call must be in Args[0], not Fun.
   999  					call := shallowCopy(context)
  1000  					call.Args = results
  1001  					res.new = call
  1002  				case *ast.ReturnStmt:
  1003  					// Inv: the call must be Results[0].
  1004  					ret := shallowCopy(context)
  1005  					ret.Results = results
  1006  					res.new = ret
  1007  				default:
  1008  					return nil, fmt.Errorf("internal error: unexpected context %T for spread call", context)
  1009  				}
  1010  				return res, nil
  1011  			}
  1012  		}
  1013  	}
  1014  
  1015  	// Special case: tail-call.
  1016  	//
  1017  	// Inlining:
  1018  	//         return f(args)
  1019  	// where:
  1020  	//         func f(params) (results) { body }
  1021  	// reduces to:
  1022  	//         { var (bindings); body }
  1023  	//         { body }
  1024  	// so long as:
  1025  	// - all parameters can be eliminated or replaced by a binding decl,
  1026  	// - call is a tail-call;
  1027  	// - all returns in body have trivial result conversions,
  1028  	//   or the caller's return type matches the callee's,
  1029  	// - there is no label conflict;
  1030  	// - no result variable is referenced by name,
  1031  	//   or implicitly by a bare return.
  1032  	//
  1033  	// The body may use defer, arbitrary control flow, and
  1034  	// multiple returns.
  1035  	//
  1036  	// TODO(adonovan): add a strategy for a 'void tail
  1037  	// call', i.e. a call statement prior to an (explicit
  1038  	// or implicit) return.
  1039  	parent, _ := callContext(caller.path)
  1040  	if ret, ok := parent.(*ast.ReturnStmt); ok &&
  1041  		len(ret.Results) == 1 &&
  1042  		tailCallSafeReturn(caller, calleeSymbol, callee) &&
  1043  		!callee.HasBareReturn &&
  1044  		(!needBindingDecl || bindingDecl != nil) &&
  1045  		!hasLabelConflict(caller.path, callee.Labels) &&
  1046  		allResultsUnreferenced {
  1047  		logf("strategy: reduce tail-call")
  1048  		body := calleeDecl.Body
  1049  		clearPositions(body)
  1050  		if needBindingDecl {
  1051  			body.List = prepend(bindingDecl.stmt, body.List...)
  1052  		}
  1053  		res.old = ret
  1054  		res.new = body
  1055  		return res, nil
  1056  	}
  1057  
  1058  	// Special case: call to void function
  1059  	//
  1060  	// Inlining:
  1061  	//         f(args)
  1062  	// where:
  1063  	//	   func f(params) { stmts }
  1064  	// reduces to:
  1065  	//         { var (bindings); stmts }
  1066  	//         { stmts }
  1067  	// so long as:
  1068  	// - callee is a void function (no returns)
  1069  	// - callee does not use defer
  1070  	// - there is no label conflict between caller and callee
  1071  	// - all parameters and result vars can be eliminated
  1072  	//   or replaced by a binding decl,
  1073  	// - caller ExprStmt is in unrestricted statement context.
  1074  	if stmt := callStmt(caller.path, true); stmt != nil &&
  1075  		(!needBindingDecl || bindingDecl != nil) &&
  1076  		!callee.HasDefer &&
  1077  		!hasLabelConflict(caller.path, callee.Labels) &&
  1078  		len(callee.Returns) == 0 {
  1079  		logf("strategy: reduce stmt-context call to { stmts }")
  1080  		body := calleeDecl.Body
  1081  		var repl ast.Stmt = body
  1082  		clearPositions(repl)
  1083  		if needBindingDecl {
  1084  			body.List = prepend(bindingDecl.stmt, body.List...)
  1085  		}
  1086  		res.old = stmt
  1087  		res.new = repl
  1088  		return res, nil
  1089  	}
  1090  
  1091  	// TODO(adonovan): parameterless call to { stmts; return expr }
  1092  	// from one of these contexts:
  1093  	//    x, y     = f()
  1094  	//    x, y    := f()
  1095  	//    var x, y = f()
  1096  	// =>
  1097  	//    var (x T1, y T2); { stmts; x, y = expr }
  1098  	//
  1099  	// Because the params are no longer declared simultaneously
  1100  	// we need to check that (for example) x ∉ freevars(T2),
  1101  	// in addition to the usual checks for arg/result conversions,
  1102  	// complex control, etc.
  1103  	// Also test cases where expr is an n-ary call (spread returns).
  1104  
  1105  	// Literalization isn't quite infallible.
  1106  	// Consider a spread call to a method in which
  1107  	// no parameters are eliminated, e.g.
  1108  	// 	new(T).f(g())
  1109  	// where
  1110  	//  	func (recv *T) f(x, y int) { body }
  1111  	//  	func g() (int, int)
  1112  	// This would be literalized to:
  1113  	// 	func (recv *T, x, y int) { body }(new(T), g()),
  1114  	// which is not a valid argument list because g() must appear alone.
  1115  	// Reject this case for now.
  1116  	if len(args) == 2 && args[0] != nil && args[1] != nil && is[*types.Tuple](args[1].typ) {
  1117  		return nil, fmt.Errorf("can't yet inline spread call to method")
  1118  	}
  1119  
  1120  	// Infallible general case: literalization.
  1121  	//
  1122  	//    func(params) { body }(args)
  1123  	//
  1124  	logf("strategy: literalization")
  1125  	funcLit := &ast.FuncLit{
  1126  		Type: calleeDecl.Type,
  1127  		Body: calleeDecl.Body,
  1128  	}
  1129  
  1130  	// Literalization can still make use of a binding
  1131  	// decl as it gives a more natural reading order:
  1132  	//
  1133  	//    func() { var params = args; body }()
  1134  	//
  1135  	// TODO(adonovan): relax the allResultsUnreferenced requirement
  1136  	// by adding a parameter-only (no named results) binding decl.
  1137  	if bindingDecl != nil && allResultsUnreferenced {
  1138  		funcLit.Type.Params.List = nil
  1139  		remainingArgs = nil
  1140  		funcLit.Body.List = prepend(bindingDecl.stmt, funcLit.Body.List...)
  1141  	}
  1142  
  1143  	// Emit a new call to a function literal in place of
  1144  	// the callee name, with appropriate replacements.
  1145  	newCall := &ast.CallExpr{
  1146  		Fun:      funcLit,
  1147  		Ellipsis: token.NoPos, // f(slice...) is always simplified
  1148  		Args:     remainingArgs,
  1149  	}
  1150  	clearPositions(newCall.Fun)
  1151  	res.old = caller.Call
  1152  	res.new = newCall
  1153  	return res, nil
  1154  }
  1155  
  1156  type argument struct {
  1157  	expr          ast.Expr
  1158  	typ           types.Type      // may be tuple for sole non-receiver arg in spread call
  1159  	constant      constant.Value  // value of argument if constant
  1160  	spread        bool            // final arg is call() assigned to multiple params
  1161  	pure          bool            // expr is pure (doesn't read variables)
  1162  	effects       bool            // expr has effects (updates variables)
  1163  	duplicable    bool            // expr may be duplicated
  1164  	freevars      map[string]bool // free names of expr
  1165  	substitutable bool            // is candidate for substitution
  1166  }
  1167  
  1168  // arguments returns the effective arguments of the call.
  1169  //
  1170  // If the receiver argument and parameter have
  1171  // different pointerness, make the "&" or "*" explicit.
  1172  //
  1173  // Also, if x.f() is shorthand for promoted method x.y.f(),
  1174  // make the .y explicit in T.f(x.y, ...).
  1175  //
  1176  // Beware that:
  1177  //
  1178  //   - a method can only be called through a selection, but only
  1179  //     the first of these two forms needs special treatment:
  1180  //
  1181  //     expr.f(args)     -> ([&*]expr, args)	MethodVal
  1182  //     T.f(recv, args)  -> (    expr, args)	MethodExpr
  1183  //
  1184  //   - the presence of a value in receiver-position in the call
  1185  //     is a property of the caller, not the callee. A method
  1186  //     (calleeDecl.Recv != nil) may be called like an ordinary
  1187  //     function.
  1188  //
  1189  //   - the types.Signatures seen by the caller (from
  1190  //     StaticCallee) and by the callee (from decl type)
  1191  //     differ in this case.
  1192  //
  1193  // In a spread call f(g()), the sole ordinary argument g(),
  1194  // always last in args, has a tuple type.
  1195  //
  1196  // We compute type-based predicates like pure, duplicable,
  1197  // freevars, etc, now, before we start modifying syntax.
  1198  func (st *state) arguments(caller *Caller, calleeDecl *ast.FuncDecl, assign1 func(*types.Var) bool) ([]*argument, error) {
  1199  	var args []*argument
  1200  
  1201  	callArgs := caller.Call.Args
  1202  	if calleeDecl.Recv != nil {
  1203  		sel := astutil.Unparen(caller.Call.Fun).(*ast.SelectorExpr)
  1204  		seln := caller.Info.Selections[sel]
  1205  		var recvArg ast.Expr
  1206  		switch seln.Kind() {
  1207  		case types.MethodVal: // recv.f(callArgs)
  1208  			recvArg = sel.X
  1209  		case types.MethodExpr: // T.f(recv, callArgs)
  1210  			recvArg = callArgs[0]
  1211  			callArgs = callArgs[1:]
  1212  		}
  1213  		if recvArg != nil {
  1214  			// Compute all the type-based predicates now,
  1215  			// before we start meddling with the syntax;
  1216  			// the meddling will update them.
  1217  			arg := &argument{
  1218  				expr:       recvArg,
  1219  				typ:        caller.Info.TypeOf(recvArg),
  1220  				constant:   caller.Info.Types[recvArg].Value,
  1221  				pure:       pure(caller.Info, assign1, recvArg),
  1222  				effects:    st.effects(caller.Info, recvArg),
  1223  				duplicable: duplicable(caller.Info, recvArg),
  1224  				freevars:   freeVars(caller.Info, recvArg),
  1225  			}
  1226  			recvArg = nil // prevent accidental use
  1227  
  1228  			// Move receiver argument recv.f(args) to argument list f(&recv, args).
  1229  			args = append(args, arg)
  1230  
  1231  			// Make field selections explicit (recv.f -> recv.y.f),
  1232  			// updating arg.{expr,typ}.
  1233  			indices := seln.Index()
  1234  			for _, index := range indices[:len(indices)-1] {
  1235  				fld := typeparams.CoreType(typeparams.Deref(arg.typ)).(*types.Struct).Field(index)
  1236  				if fld.Pkg() != caller.Types && !fld.Exported() {
  1237  					return nil, fmt.Errorf("in %s, implicit reference to unexported field .%s cannot be made explicit",
  1238  						debugFormatNode(caller.Fset, caller.Call.Fun),
  1239  						fld.Name())
  1240  				}
  1241  				if isPointer(arg.typ) {
  1242  					arg.pure = false // implicit *ptr operation => impure
  1243  				}
  1244  				arg.expr = &ast.SelectorExpr{
  1245  					X:   arg.expr,
  1246  					Sel: makeIdent(fld.Name()),
  1247  				}
  1248  				arg.typ = fld.Type()
  1249  				arg.duplicable = false
  1250  			}
  1251  
  1252  			// Make * or & explicit.
  1253  			argIsPtr := isPointer(arg.typ)
  1254  			paramIsPtr := isPointer(seln.Obj().Type().Underlying().(*types.Signature).Recv().Type())
  1255  			if !argIsPtr && paramIsPtr {
  1256  				// &recv
  1257  				arg.expr = &ast.UnaryExpr{Op: token.AND, X: arg.expr}
  1258  				arg.typ = types.NewPointer(arg.typ)
  1259  			} else if argIsPtr && !paramIsPtr {
  1260  				// *recv
  1261  				arg.expr = &ast.StarExpr{X: arg.expr}
  1262  				arg.typ = typeparams.Deref(arg.typ)
  1263  				arg.duplicable = false
  1264  				arg.pure = false
  1265  			}
  1266  		}
  1267  	}
  1268  	for _, expr := range callArgs {
  1269  		tv := caller.Info.Types[expr]
  1270  		args = append(args, &argument{
  1271  			expr:       expr,
  1272  			typ:        tv.Type,
  1273  			constant:   tv.Value,
  1274  			spread:     is[*types.Tuple](tv.Type), // => last
  1275  			pure:       pure(caller.Info, assign1, expr),
  1276  			effects:    st.effects(caller.Info, expr),
  1277  			duplicable: duplicable(caller.Info, expr),
  1278  			freevars:   freeVars(caller.Info, expr),
  1279  		})
  1280  	}
  1281  
  1282  	// Re-typecheck each constant argument expression in a neutral context.
  1283  	//
  1284  	// In a call such as func(int16){}(1), the type checker infers
  1285  	// the type "int16", not "untyped int", for the argument 1,
  1286  	// because it has incorporated information from the left-hand
  1287  	// side of the assignment implicit in parameter passing, but
  1288  	// of course in a different context, the expression 1 may have
  1289  	// a different type.
  1290  	//
  1291  	// So, we must use CheckExpr to recompute the type of the
  1292  	// argument in a neutral context to find its inherent type.
  1293  	// (This is arguably a bug in go/types, but I'm pretty certain
  1294  	// I requested it be this way long ago... -adonovan)
  1295  	//
  1296  	// This is only needed for constants. Other implicit
  1297  	// assignment conversions, such as unnamed-to-named struct or
  1298  	// chan to <-chan, do not result in the type-checker imposing
  1299  	// the LHS type on the RHS value.
  1300  	for _, arg := range args {
  1301  		if arg.constant == nil {
  1302  			continue
  1303  		}
  1304  		info := &types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
  1305  		if err := types.CheckExpr(caller.Fset, caller.Types, caller.Call.Pos(), arg.expr, info); err != nil {
  1306  			return nil, err
  1307  		}
  1308  		arg.typ = info.TypeOf(arg.expr)
  1309  	}
  1310  
  1311  	return args, nil
  1312  }
  1313  
  1314  type parameter struct {
  1315  	obj       *types.Var // parameter var from caller's signature
  1316  	fieldType ast.Expr   // syntax of type, from calleeDecl.Type.{Recv,Params}
  1317  	info      *paramInfo // information from AnalyzeCallee
  1318  	variadic  bool       // (final) parameter is unsimplified ...T
  1319  }
  1320  
  1321  // substitute implements parameter elimination by substitution.
  1322  //
  1323  // It considers each parameter and its corresponding argument in turn
  1324  // and evaluate these conditions:
  1325  //
  1326  //   - the parameter is neither address-taken nor assigned;
  1327  //   - the argument is pure;
  1328  //   - if the parameter refcount is zero, the argument must
  1329  //     not contain the last use of a local var;
  1330  //   - if the parameter refcount is > 1, the argument must be duplicable;
  1331  //   - the argument (or types.Default(argument) if it's untyped) has
  1332  //     the same type as the parameter.
  1333  //
  1334  // If all conditions are met then the parameter can be substituted and
  1335  // each reference to it replaced by the argument. In that case, the
  1336  // replaceCalleeID function is called for each reference to the
  1337  // parameter, and is provided with its relative offset and replacement
  1338  // expression (argument), and the corresponding elements of params and
  1339  // args are replaced by nil.
  1340  func substitute(logf func(string, ...any), caller *Caller, params []*parameter, args []*argument, effects []int, falcon falconResult, replaceCalleeID func(offset int, repl ast.Expr)) {
  1341  	// Inv:
  1342  	//  in        calls to     variadic, len(args) >= len(params)-1
  1343  	//  in spread calls to non-variadic, len(args) <  len(params)
  1344  	//  in spread calls to     variadic, len(args) <= len(params)
  1345  	// (In spread calls len(args) = 1, or 2 if call has receiver.)
  1346  	// Non-spread variadics have been simplified away already,
  1347  	// so the args[i] lookup is safe if we stop after the spread arg.
  1348  next:
  1349  	for i, param := range params {
  1350  		arg := args[i]
  1351  		// Check argument against parameter.
  1352  		//
  1353  		// Beware: don't use types.Info on arg since
  1354  		// the syntax may be synthetic (not created by parser)
  1355  		// and thus lacking positions and types;
  1356  		// do it earlier (see pure/duplicable/freevars).
  1357  
  1358  		if arg.spread {
  1359  			// spread => last argument, but not always last parameter
  1360  			logf("keeping param %q and following ones: argument %s is spread",
  1361  				param.info.Name, debugFormatNode(caller.Fset, arg.expr))
  1362  			return // give up
  1363  		}
  1364  		assert(!param.variadic, "unsimplified variadic parameter")
  1365  		if param.info.Escapes {
  1366  			logf("keeping param %q: escapes from callee", param.info.Name)
  1367  			continue
  1368  		}
  1369  		if param.info.Assigned {
  1370  			logf("keeping param %q: assigned by callee", param.info.Name)
  1371  			continue // callee needs the parameter variable
  1372  		}
  1373  		if len(param.info.Refs) > 1 && !arg.duplicable {
  1374  			logf("keeping param %q: argument is not duplicable", param.info.Name)
  1375  			continue // incorrect or poor style to duplicate an expression
  1376  		}
  1377  		if len(param.info.Refs) == 0 {
  1378  			if arg.effects {
  1379  				logf("keeping param %q: though unreferenced, it has effects", param.info.Name)
  1380  				continue
  1381  			}
  1382  
  1383  			// If the caller is within a function body,
  1384  			// eliminating an unreferenced parameter might
  1385  			// remove the last reference to a caller local var.
  1386  			if caller.enclosingFunc != nil {
  1387  				for free := range arg.freevars {
  1388  					// TODO(rfindley): we can get this 100% right by looking for
  1389  					// references among other arguments which have non-zero references
  1390  					// within the callee.
  1391  					if v, ok := caller.lookup(free).(*types.Var); ok && within(v.Pos(), caller.enclosingFunc.Body) && !isUsedOutsideCall(caller, v) {
  1392  						logf("keeping param %q: arg contains perhaps the last reference to caller local %v @ %v",
  1393  							param.info.Name, v, caller.Fset.PositionFor(v.Pos(), false))
  1394  						continue next
  1395  					}
  1396  				}
  1397  			}
  1398  		}
  1399  
  1400  		// Check for shadowing.
  1401  		//
  1402  		// Consider inlining a call f(z, 1) to
  1403  		// func f(x, y int) int { z := y; return x + y + z }:
  1404  		// we can't replace x in the body by z (or any
  1405  		// expression that has z as a free identifier)
  1406  		// because there's an intervening declaration of z
  1407  		// that would shadow the caller's one.
  1408  		for free := range arg.freevars {
  1409  			if param.info.Shadow[free] {
  1410  				logf("keeping param %q: cannot replace with argument as it has free ref to %s that is shadowed", param.info.Name, free)
  1411  				continue next // shadowing conflict
  1412  			}
  1413  		}
  1414  
  1415  		arg.substitutable = true // may be substituted, if effects permit
  1416  	}
  1417  
  1418  	// Reject constant arguments as substitution candidates
  1419  	// if they cause violation of falcon constraints.
  1420  	checkFalconConstraints(logf, params, args, falcon)
  1421  
  1422  	// As a final step, introduce bindings to resolve any
  1423  	// evaluation order hazards. This must be done last, as
  1424  	// additional subsequent bindings could introduce new hazards.
  1425  	resolveEffects(logf, args, effects)
  1426  
  1427  	// The remaining candidates are safe to substitute.
  1428  	for i, param := range params {
  1429  		if arg := args[i]; arg.substitutable {
  1430  
  1431  			// Wrap the argument in an explicit conversion if
  1432  			// substitution might materially change its type.
  1433  			// (We already did the necessary shadowing check
  1434  			// on the parameter type syntax.)
  1435  			//
  1436  			// This is only needed for substituted arguments. All
  1437  			// other arguments are given explicit types in either
  1438  			// a binding decl or when using the literalization
  1439  			// strategy.
  1440  			if len(param.info.Refs) > 0 && !trivialConversion(args[i].constant, args[i].typ, params[i].obj.Type()) {
  1441  				arg.expr = convert(params[i].fieldType, arg.expr)
  1442  				logf("param %q: adding explicit %s -> %s conversion around argument",
  1443  					param.info.Name, args[i].typ, params[i].obj.Type())
  1444  			}
  1445  
  1446  			// It is safe to substitute param and replace it with arg.
  1447  			// The formatter introduces parens as needed for precedence.
  1448  			//
  1449  			// Because arg.expr belongs to the caller,
  1450  			// we clone it before splicing it into the callee tree.
  1451  			logf("replacing parameter %q by argument %q",
  1452  				param.info.Name, debugFormatNode(caller.Fset, arg.expr))
  1453  			for _, ref := range param.info.Refs {
  1454  				replaceCalleeID(ref, internalastutil.CloneNode(arg.expr).(ast.Expr))
  1455  			}
  1456  			params[i] = nil // substituted
  1457  			args[i] = nil   // substituted
  1458  		}
  1459  	}
  1460  }
  1461  
  1462  // isUsedOutsideCall reports whether v is used outside of caller.Call, within
  1463  // the body of caller.enclosingFunc.
  1464  func isUsedOutsideCall(caller *Caller, v *types.Var) bool {
  1465  	used := false
  1466  	ast.Inspect(caller.enclosingFunc.Body, func(n ast.Node) bool {
  1467  		if n == caller.Call {
  1468  			return false
  1469  		}
  1470  		switch n := n.(type) {
  1471  		case *ast.Ident:
  1472  			if use := caller.Info.Uses[n]; use == v {
  1473  				used = true
  1474  			}
  1475  		case *ast.FuncType:
  1476  			// All params are used.
  1477  			for _, fld := range n.Params.List {
  1478  				for _, n := range fld.Names {
  1479  					if def := caller.Info.Defs[n]; def == v {
  1480  						used = true
  1481  					}
  1482  				}
  1483  			}
  1484  		}
  1485  		return !used // keep going until we find a use
  1486  	})
  1487  	return used
  1488  }
  1489  
  1490  // checkFalconConstraints checks whether constant arguments
  1491  // are safe to substitute (e.g. s[i] -> ""[0] is not safe.)
  1492  //
  1493  // Any failed constraint causes us to reject all constant arguments as
  1494  // substitution candidates (by clearing args[i].substitution=false).
  1495  //
  1496  // TODO(adonovan): we could obtain a finer result rejecting only the
  1497  // freevars of each failed constraint, and processing constraints in
  1498  // order of increasing arity, but failures are quite rare.
  1499  func checkFalconConstraints(logf func(string, ...any), params []*parameter, args []*argument, falcon falconResult) {
  1500  	// Create a dummy package, as this is the only
  1501  	// way to create an environment for CheckExpr.
  1502  	pkg := types.NewPackage("falcon", "falcon")
  1503  
  1504  	// Declare types used by constraints.
  1505  	for _, typ := range falcon.Types {
  1506  		logf("falcon env: type %s %s", typ.Name, types.Typ[typ.Kind])
  1507  		pkg.Scope().Insert(types.NewTypeName(token.NoPos, pkg, typ.Name, types.Typ[typ.Kind]))
  1508  	}
  1509  
  1510  	// Declared constants and variables for for parameters.
  1511  	nconst := 0
  1512  	for i, param := range params {
  1513  		name := param.info.Name
  1514  		if name == "" {
  1515  			continue // unreferenced
  1516  		}
  1517  		arg := args[i]
  1518  		if arg.constant != nil && arg.substitutable && param.info.FalconType != "" {
  1519  			t := pkg.Scope().Lookup(param.info.FalconType).Type()
  1520  			pkg.Scope().Insert(types.NewConst(token.NoPos, pkg, name, t, arg.constant))
  1521  			logf("falcon env: const %s %s = %v", name, param.info.FalconType, arg.constant)
  1522  			nconst++
  1523  		} else {
  1524  			pkg.Scope().Insert(types.NewVar(token.NoPos, pkg, name, arg.typ))
  1525  			logf("falcon env: var %s %s", name, arg.typ)
  1526  		}
  1527  	}
  1528  	if nconst == 0 {
  1529  		return // nothing to do
  1530  	}
  1531  
  1532  	// Parse and evaluate the constraints in the environment.
  1533  	fset := token.NewFileSet()
  1534  	for _, falcon := range falcon.Constraints {
  1535  		expr, err := parser.ParseExprFrom(fset, "falcon", falcon, 0)
  1536  		if err != nil {
  1537  			panic(fmt.Sprintf("failed to parse falcon constraint %s: %v", falcon, err))
  1538  		}
  1539  		if err := types.CheckExpr(fset, pkg, token.NoPos, expr, nil); err != nil {
  1540  			logf("falcon: constraint %s violated: %v", falcon, err)
  1541  			for j, arg := range args {
  1542  				if arg.constant != nil && arg.substitutable {
  1543  					logf("keeping param %q due falcon violation", params[j].info.Name)
  1544  					arg.substitutable = false
  1545  				}
  1546  			}
  1547  			break
  1548  		}
  1549  		logf("falcon: constraint %s satisfied", falcon)
  1550  	}
  1551  }
  1552  
  1553  // resolveEffects marks arguments as non-substitutable to resolve
  1554  // hazards resulting from the callee evaluation order described by the
  1555  // effects list.
  1556  //
  1557  // To do this, each argument is categorized as a read (R), write (W),
  1558  // or pure. A hazard occurs when the order of evaluation of a W
  1559  // changes with respect to any R or W. Pure arguments can be
  1560  // effectively ignored, as they can be safely evaluated in any order.
  1561  //
  1562  // The callee effects list contains the index of each parameter in the
  1563  // order it is first evaluated during execution of the callee. In
  1564  // addition, the two special values R∞ and W∞ indicate the relative
  1565  // position of the callee's first non-parameter read and its first
  1566  // effects (or other unknown behavior).
  1567  // For example, the list [0 2 1 R∞ 3 W∞] for func(a, b, c, d)
  1568  // indicates that the callee referenced parameters a, c, and b,
  1569  // followed by an arbitrary read, then parameter d, and finally
  1570  // unknown behavior.
  1571  //
  1572  // When an argument is marked as not substitutable, we say that it is
  1573  // 'bound', in the sense that its evaluation occurs in a binding decl
  1574  // or literalized call. Such bindings always occur in the original
  1575  // callee parameter order.
  1576  //
  1577  // In this context, "resolving hazards" means binding arguments so
  1578  // that they are evaluated in a valid, hazard-free order. A trivial
  1579  // solution to this problem would be to bind all arguments, but of
  1580  // course that's not useful. The goal is to bind as few arguments as
  1581  // possible.
  1582  //
  1583  // The algorithm proceeds by inspecting arguments in reverse parameter
  1584  // order (right to left), preserving the invariant that every
  1585  // higher-ordered argument is either already substituted or does not
  1586  // need to be substituted. At each iteration, if there is an
  1587  // evaluation hazard in the callee effects relative to the current
  1588  // argument, the argument must be bound. Subsequently, if the argument
  1589  // is bound for any reason, each lower-ordered argument must also be
  1590  // bound if either the argument or lower-order argument is a
  1591  // W---otherwise the binding itself would introduce a hazard.
  1592  //
  1593  // Thus, after each iteration, there are no hazards relative to the
  1594  // current argument. Subsequent iterations cannot introduce hazards
  1595  // with that argument because they can result only in additional
  1596  // binding of lower-ordered arguments.
  1597  func resolveEffects(logf func(string, ...any), args []*argument, effects []int) {
  1598  	effectStr := func(effects bool, idx int) string {
  1599  		i := fmt.Sprint(idx)
  1600  		if idx == len(args) {
  1601  			i = "∞"
  1602  		}
  1603  		return string("RW"[btoi(effects)]) + i
  1604  	}
  1605  	for i := len(args) - 1; i >= 0; i-- {
  1606  		argi := args[i]
  1607  		if argi.substitutable && !argi.pure {
  1608  			// i is not bound: check whether it must be bound due to hazards.
  1609  			idx := index(effects, i)
  1610  			if idx >= 0 {
  1611  				for _, j := range effects[:idx] {
  1612  					var (
  1613  						ji int  // effective param index
  1614  						jw bool // j is a write
  1615  					)
  1616  					if j == winf || j == rinf {
  1617  						jw = j == winf
  1618  						ji = len(args)
  1619  					} else {
  1620  						jw = args[j].effects
  1621  						ji = j
  1622  					}
  1623  					if ji > i && (jw || argi.effects) { // out of order evaluation
  1624  						logf("binding argument %s: preceded by %s",
  1625  							effectStr(argi.effects, i), effectStr(jw, ji))
  1626  						argi.substitutable = false
  1627  						break
  1628  					}
  1629  				}
  1630  			}
  1631  		}
  1632  		if !argi.substitutable {
  1633  			for j := 0; j < i; j++ {
  1634  				argj := args[j]
  1635  				if argj.pure {
  1636  					continue
  1637  				}
  1638  				if (argi.effects || argj.effects) && argj.substitutable {
  1639  					logf("binding argument %s: %s is bound",
  1640  						effectStr(argj.effects, j), effectStr(argi.effects, i))
  1641  					argj.substitutable = false
  1642  				}
  1643  			}
  1644  		}
  1645  	}
  1646  }
  1647  
  1648  // updateCalleeParams updates the calleeDecl syntax to remove
  1649  // substituted parameters and move the receiver (if any) to the head
  1650  // of the ordinary parameters.
  1651  func updateCalleeParams(calleeDecl *ast.FuncDecl, params []*parameter) {
  1652  	// The logic is fiddly because of the three forms of ast.Field:
  1653  	//
  1654  	//	func(int), func(x int), func(x, y int)
  1655  	//
  1656  	// Also, ensure that all remaining parameters are named
  1657  	// to avoid a mix of named/unnamed when joining (recv, params...).
  1658  	// func (T) f(int, bool) -> (_ T, _ int, _ bool)
  1659  	// (Strictly, we need do this only for methods and only when
  1660  	// the namednesses of Recv and Params differ; that might be tidier.)
  1661  
  1662  	paramIdx := 0 // index in original parameter list (incl. receiver)
  1663  	var newParams []*ast.Field
  1664  	filterParams := func(field *ast.Field) {
  1665  		var names []*ast.Ident
  1666  		if field.Names == nil {
  1667  			// Unnamed parameter field (e.g. func f(int)
  1668  			if params[paramIdx] != nil {
  1669  				// Give it an explicit name "_" since we will
  1670  				// make the receiver (if any) a regular parameter
  1671  				// and one cannot mix named and unnamed parameters.
  1672  				names = append(names, makeIdent("_"))
  1673  			}
  1674  			paramIdx++
  1675  		} else {
  1676  			// Named parameter field e.g. func f(x, y int)
  1677  			// Remove substituted parameters in place.
  1678  			// If all were substituted, delete field.
  1679  			for _, id := range field.Names {
  1680  				if pinfo := params[paramIdx]; pinfo != nil {
  1681  					// Rename unreferenced parameters with "_".
  1682  					// This is crucial for binding decls, since
  1683  					// unlike parameters, they are subject to
  1684  					// "unreferenced var" checks.
  1685  					if len(pinfo.info.Refs) == 0 {
  1686  						id = makeIdent("_")
  1687  					}
  1688  					names = append(names, id)
  1689  				}
  1690  				paramIdx++
  1691  			}
  1692  		}
  1693  		if names != nil {
  1694  			newParams = append(newParams, &ast.Field{
  1695  				Names: names,
  1696  				Type:  field.Type,
  1697  			})
  1698  		}
  1699  	}
  1700  	if calleeDecl.Recv != nil {
  1701  		filterParams(calleeDecl.Recv.List[0])
  1702  		calleeDecl.Recv = nil
  1703  	}
  1704  	for _, field := range calleeDecl.Type.Params.List {
  1705  		filterParams(field)
  1706  	}
  1707  	calleeDecl.Type.Params.List = newParams
  1708  }
  1709  
  1710  // bindingDeclInfo records information about the binding decl produced by
  1711  // createBindingDecl.
  1712  type bindingDeclInfo struct {
  1713  	names map[string]bool // names bound by the binding decl; possibly empty
  1714  	stmt  ast.Stmt        // the binding decl itself
  1715  }
  1716  
  1717  // createBindingDecl constructs a "binding decl" that implements
  1718  // parameter assignment and declares any named result variables
  1719  // referenced by the callee. It returns nil if there were no
  1720  // unsubstituted parameters.
  1721  //
  1722  // It may not always be possible to create the decl (e.g. due to
  1723  // shadowing), in which case it also returns nil; but if it succeeds,
  1724  // the declaration may be used by reduction strategies to relax the
  1725  // requirement that all parameters have been substituted.
  1726  //
  1727  // For example, a call:
  1728  //
  1729  //	f(a0, a1, a2)
  1730  //
  1731  // where:
  1732  //
  1733  //	func f(p0, p1 T0, p2 T1) { body }
  1734  //
  1735  // reduces to:
  1736  //
  1737  //	{
  1738  //	  var (
  1739  //	    p0, p1 T0 = a0, a1
  1740  //	    p2     T1 = a2
  1741  //	  )
  1742  //	  body
  1743  //	}
  1744  //
  1745  // so long as p0, p1 ∉ freevars(T1) or freevars(a2), and so on,
  1746  // because each spec is statically resolved in sequence and
  1747  // dynamically assigned in sequence. By contrast, all
  1748  // parameters are resolved simultaneously and assigned
  1749  // simultaneously.
  1750  //
  1751  // The pX names should already be blank ("_") if the parameter
  1752  // is unreferenced; this avoids "unreferenced local var" checks.
  1753  //
  1754  // Strategies may impose additional checks on return
  1755  // conversions, labels, defer, etc.
  1756  func createBindingDecl(logf func(string, ...any), caller *Caller, args []*argument, calleeDecl *ast.FuncDecl, results []*paramInfo) *bindingDeclInfo {
  1757  	// Spread calls are tricky as they may not align with the
  1758  	// parameters' field groupings nor types.
  1759  	// For example, given
  1760  	//   func g() (int, string)
  1761  	// the call
  1762  	//   f(g())
  1763  	// is legal with these decls of f:
  1764  	//   func f(int, string)
  1765  	//   func f(x, y any)
  1766  	//   func f(x, y ...any)
  1767  	// TODO(adonovan): support binding decls for spread calls by
  1768  	// splitting parameter groupings as needed.
  1769  	if lastArg := last(args); lastArg != nil && lastArg.spread {
  1770  		logf("binding decls not yet supported for spread calls")
  1771  		return nil
  1772  	}
  1773  
  1774  	var (
  1775  		specs []ast.Spec
  1776  		names = make(map[string]bool) // names defined by previous specs
  1777  	)
  1778  	// shadow reports whether any name referenced by spec is
  1779  	// shadowed by a name declared by a previous spec (since,
  1780  	// unlike parameters, each spec of a var decl is within the
  1781  	// scope of the previous specs).
  1782  	shadow := func(spec *ast.ValueSpec) bool {
  1783  		// Compute union of free names of type and values
  1784  		// and detect shadowing. Values is the arguments
  1785  		// (caller syntax), so we can use type info.
  1786  		// But Type is the untyped callee syntax,
  1787  		// so we have to use a syntax-only algorithm.
  1788  		free := make(map[string]bool)
  1789  		for _, value := range spec.Values {
  1790  			for name := range freeVars(caller.Info, value) {
  1791  				free[name] = true
  1792  			}
  1793  		}
  1794  		freeishNames(free, spec.Type)
  1795  		for name := range free {
  1796  			if names[name] {
  1797  				logf("binding decl would shadow free name %q", name)
  1798  				return true
  1799  			}
  1800  		}
  1801  		for _, id := range spec.Names {
  1802  			if id.Name != "_" {
  1803  				names[id.Name] = true
  1804  			}
  1805  		}
  1806  		return false
  1807  	}
  1808  
  1809  	// parameters
  1810  	//
  1811  	// Bind parameters that were not eliminated through
  1812  	// substitution. (Non-nil arguments correspond to the
  1813  	// remaining parameters in calleeDecl.)
  1814  	var values []ast.Expr
  1815  	for _, arg := range args {
  1816  		if arg != nil {
  1817  			values = append(values, arg.expr)
  1818  		}
  1819  	}
  1820  	for _, field := range calleeDecl.Type.Params.List {
  1821  		// Each field (param group) becomes a ValueSpec.
  1822  		spec := &ast.ValueSpec{
  1823  			Names:  field.Names,
  1824  			Type:   field.Type,
  1825  			Values: values[:len(field.Names)],
  1826  		}
  1827  		values = values[len(field.Names):]
  1828  		if shadow(spec) {
  1829  			return nil
  1830  		}
  1831  		specs = append(specs, spec)
  1832  	}
  1833  	assert(len(values) == 0, "args/params mismatch")
  1834  
  1835  	// results
  1836  	//
  1837  	// Add specs to declare any named result
  1838  	// variables that are referenced by the body.
  1839  	if calleeDecl.Type.Results != nil {
  1840  		resultIdx := 0
  1841  		for _, field := range calleeDecl.Type.Results.List {
  1842  			if field.Names == nil {
  1843  				resultIdx++
  1844  				continue // unnamed field
  1845  			}
  1846  			var names []*ast.Ident
  1847  			for _, id := range field.Names {
  1848  				if len(results[resultIdx].Refs) > 0 {
  1849  					names = append(names, id)
  1850  				}
  1851  				resultIdx++
  1852  			}
  1853  			if len(names) > 0 {
  1854  				spec := &ast.ValueSpec{
  1855  					Names: names,
  1856  					Type:  field.Type,
  1857  				}
  1858  				if shadow(spec) {
  1859  					return nil
  1860  				}
  1861  				specs = append(specs, spec)
  1862  			}
  1863  		}
  1864  	}
  1865  
  1866  	if len(specs) == 0 {
  1867  		logf("binding decl not needed: all parameters substituted")
  1868  		return nil
  1869  	}
  1870  
  1871  	stmt := &ast.DeclStmt{
  1872  		Decl: &ast.GenDecl{
  1873  			Tok:   token.VAR,
  1874  			Specs: specs,
  1875  		},
  1876  	}
  1877  	logf("binding decl: %s", debugFormatNode(caller.Fset, stmt))
  1878  	return &bindingDeclInfo{names: names, stmt: stmt}
  1879  }
  1880  
  1881  // lookup does a symbol lookup in the lexical environment of the caller.
  1882  func (caller *Caller) lookup(name string) types.Object {
  1883  	pos := caller.Call.Pos()
  1884  	for _, n := range caller.path {
  1885  		if scope := scopeFor(caller.Info, n); scope != nil {
  1886  			if _, obj := scope.LookupParent(name, pos); obj != nil {
  1887  				return obj
  1888  			}
  1889  		}
  1890  	}
  1891  	return nil
  1892  }
  1893  
  1894  func scopeFor(info *types.Info, n ast.Node) *types.Scope {
  1895  	// The function body scope (containing not just params)
  1896  	// is associated with the function's type, not body.
  1897  	switch fn := n.(type) {
  1898  	case *ast.FuncDecl:
  1899  		n = fn.Type
  1900  	case *ast.FuncLit:
  1901  		n = fn.Type
  1902  	}
  1903  	return info.Scopes[n]
  1904  }
  1905  
  1906  // -- predicates over expressions --
  1907  
  1908  // freeVars returns the names of all free identifiers of e:
  1909  // those lexically referenced by it but not defined within it.
  1910  // (Fields and methods are not included.)
  1911  func freeVars(info *types.Info, e ast.Expr) map[string]bool {
  1912  	free := make(map[string]bool)
  1913  	ast.Inspect(e, func(n ast.Node) bool {
  1914  		if id, ok := n.(*ast.Ident); ok {
  1915  			// The isField check is so that we don't treat T{f: 0} as a ref to f.
  1916  			if obj, ok := info.Uses[id]; ok && !within(obj.Pos(), e) && !isField(obj) {
  1917  				free[obj.Name()] = true
  1918  			}
  1919  		}
  1920  		return true
  1921  	})
  1922  	return free
  1923  }
  1924  
  1925  // freeishNames computes an over-approximation to the free names
  1926  // of the type syntax t, inserting values into the map.
  1927  //
  1928  // Because we don't have go/types annotations, we can't give an exact
  1929  // result in all cases. In particular, an array type [n]T might have a
  1930  // size such as unsafe.Sizeof(func() int{stmts...}()) and now the
  1931  // precise answer depends upon all the statement syntax too. But that
  1932  // never happens in practice.
  1933  func freeishNames(free map[string]bool, t ast.Expr) {
  1934  	var visit func(n ast.Node) bool
  1935  	visit = func(n ast.Node) bool {
  1936  		switch n := n.(type) {
  1937  		case *ast.Ident:
  1938  			free[n.Name] = true
  1939  
  1940  		case *ast.SelectorExpr:
  1941  			ast.Inspect(n.X, visit)
  1942  			return false // don't visit .Sel
  1943  
  1944  		case *ast.Field:
  1945  			ast.Inspect(n.Type, visit)
  1946  			// Don't visit .Names:
  1947  			// FuncType parameters, interface methods, struct fields
  1948  			return false
  1949  		}
  1950  		return true
  1951  	}
  1952  	ast.Inspect(t, visit)
  1953  }
  1954  
  1955  // effects reports whether an expression might change the state of the
  1956  // program (through function calls and channel receives) and affect
  1957  // the evaluation of subsequent expressions.
  1958  func (st *state) effects(info *types.Info, expr ast.Expr) bool {
  1959  	effects := false
  1960  	ast.Inspect(expr, func(n ast.Node) bool {
  1961  		switch n := n.(type) {
  1962  		case *ast.FuncLit:
  1963  			return false // prune descent
  1964  
  1965  		case *ast.CallExpr:
  1966  			if info.Types[n.Fun].IsType() {
  1967  				// A conversion T(x) has only the effect of its operand.
  1968  			} else if !callsPureBuiltin(info, n) {
  1969  				// A handful of built-ins have no effect
  1970  				// beyond those of their arguments.
  1971  				// All other calls (including append, copy, recover)
  1972  				// have unknown effects.
  1973  				//
  1974  				// As with 'pure', there is room for
  1975  				// improvement by inspecting the callee.
  1976  				effects = true
  1977  			}
  1978  
  1979  		case *ast.UnaryExpr:
  1980  			if n.Op == token.ARROW { // <-ch
  1981  				effects = true
  1982  			}
  1983  		}
  1984  		return true
  1985  	})
  1986  
  1987  	// Even if consideration of effects is not desired,
  1988  	// we continue to compute, log, and discard them.
  1989  	if st.opts.IgnoreEffects && effects {
  1990  		effects = false
  1991  		st.opts.Logf("ignoring potential effects of argument %s",
  1992  			debugFormatNode(st.caller.Fset, expr))
  1993  	}
  1994  
  1995  	return effects
  1996  }
  1997  
  1998  // pure reports whether an expression has the same result no matter
  1999  // when it is executed relative to other expressions, so it can be
  2000  // commuted with any other expression or statement without changing
  2001  // its meaning.
  2002  //
  2003  // An expression is considered impure if it reads the contents of any
  2004  // variable, with the exception of "single assignment" local variables
  2005  // (as classified by the provided callback), which are never updated
  2006  // after their initialization.
  2007  //
  2008  // Pure does not imply duplicable: for example, new(T) and T{} are
  2009  // pure expressions but both return a different value each time they
  2010  // are evaluated, so they are not safe to duplicate.
  2011  //
  2012  // Purity does not imply freedom from run-time panics. We assume that
  2013  // target programs do not encounter run-time panics nor depend on them
  2014  // for correct operation.
  2015  //
  2016  // TODO(adonovan): add unit tests of this function.
  2017  func pure(info *types.Info, assign1 func(*types.Var) bool, e ast.Expr) bool {
  2018  	var pure func(e ast.Expr) bool
  2019  	pure = func(e ast.Expr) bool {
  2020  		switch e := e.(type) {
  2021  		case *ast.ParenExpr:
  2022  			return pure(e.X)
  2023  
  2024  		case *ast.Ident:
  2025  			if v, ok := info.Uses[e].(*types.Var); ok {
  2026  				// In general variables are impure
  2027  				// as they may be updated, but
  2028  				// single-assignment local variables
  2029  				// never change value.
  2030  				//
  2031  				// We assume all package-level variables
  2032  				// may be updated, but for non-exported
  2033  				// ones we could do better by analyzing
  2034  				// the complete package.
  2035  				return !isPkgLevel(v) && assign1(v)
  2036  			}
  2037  
  2038  			// All other kinds of reference are pure.
  2039  			return true
  2040  
  2041  		case *ast.FuncLit:
  2042  			// A function literal may allocate a closure that
  2043  			// references mutable variables, but mutation
  2044  			// cannot be observed without calling the function,
  2045  			// and calls are considered impure.
  2046  			return true
  2047  
  2048  		case *ast.BasicLit:
  2049  			return true
  2050  
  2051  		case *ast.UnaryExpr: // + - ! ^ & but not <-
  2052  			return e.Op != token.ARROW && pure(e.X)
  2053  
  2054  		case *ast.BinaryExpr: // arithmetic, shifts, comparisons, &&/||
  2055  			return pure(e.X) && pure(e.Y)
  2056  
  2057  		case *ast.CallExpr:
  2058  			// A conversion is as pure as its operand.
  2059  			if info.Types[e.Fun].IsType() {
  2060  				return pure(e.Args[0])
  2061  			}
  2062  
  2063  			// Calls to some built-ins are as pure as their arguments.
  2064  			if callsPureBuiltin(info, e) {
  2065  				for _, arg := range e.Args {
  2066  					if !pure(arg) {
  2067  						return false
  2068  					}
  2069  				}
  2070  				return true
  2071  			}
  2072  
  2073  			// All other calls are impure, so we can
  2074  			// reject them without even looking at e.Fun.
  2075  			//
  2076  			// More sophisticated analysis could infer purity in
  2077  			// commonly used functions such as strings.Contains;
  2078  			// perhaps we could offer the client a hook so that
  2079  			// go/analysis-based implementation could exploit the
  2080  			// results of a purity analysis. But that would make
  2081  			// the inliner's choices harder to explain.
  2082  			return false
  2083  
  2084  		case *ast.CompositeLit:
  2085  			// T{...} is as pure as its elements.
  2086  			for _, elt := range e.Elts {
  2087  				if kv, ok := elt.(*ast.KeyValueExpr); ok {
  2088  					if !pure(kv.Value) {
  2089  						return false
  2090  					}
  2091  					if id, ok := kv.Key.(*ast.Ident); ok {
  2092  						if v, ok := info.Uses[id].(*types.Var); ok && v.IsField() {
  2093  							continue // struct {field: value}
  2094  						}
  2095  					}
  2096  					// map/slice/array {key: value}
  2097  					if !pure(kv.Key) {
  2098  						return false
  2099  					}
  2100  
  2101  				} else if !pure(elt) {
  2102  					return false
  2103  				}
  2104  			}
  2105  			return true
  2106  
  2107  		case *ast.SelectorExpr:
  2108  			if seln, ok := info.Selections[e]; ok {
  2109  
  2110  				// See types.SelectionKind for background.
  2111  				switch seln.Kind() {
  2112  				case types.MethodExpr:
  2113  					// A method expression T.f acts like a
  2114  					// reference to a func decl, so it is pure.
  2115  					return true
  2116  
  2117  				case types.MethodVal, types.FieldVal:
  2118  					// A field or method selection x.f is pure
  2119  					// if x is pure and the selection does
  2120  					// not indirect a pointer.
  2121  					return !indirectSelection(seln) && pure(e.X)
  2122  
  2123  				default:
  2124  					panic(seln)
  2125  				}
  2126  			} else {
  2127  				// A qualified identifier is
  2128  				// treated like an unqualified one.
  2129  				return pure(e.Sel)
  2130  			}
  2131  
  2132  		case *ast.StarExpr:
  2133  			return false // *ptr depends on the state of the heap
  2134  
  2135  		default:
  2136  			return false
  2137  		}
  2138  	}
  2139  	return pure(e)
  2140  }
  2141  
  2142  // callsPureBuiltin reports whether call is a call of a built-in
  2143  // function that is a pure computation over its operands (analogous to
  2144  // a + operator). Because it does not depend on program state, it may
  2145  // be evaluated at any point--though not necessarily at multiple
  2146  // points (consider new, make).
  2147  func callsPureBuiltin(info *types.Info, call *ast.CallExpr) bool {
  2148  	if id, ok := astutil.Unparen(call.Fun).(*ast.Ident); ok {
  2149  		if b, ok := info.ObjectOf(id).(*types.Builtin); ok {
  2150  			switch b.Name() {
  2151  			case "len", "cap", "complex", "imag", "real", "make", "new", "max", "min":
  2152  				return true
  2153  			}
  2154  			// Not: append clear close copy delete panic print println recover
  2155  		}
  2156  	}
  2157  	return false
  2158  }
  2159  
  2160  // duplicable reports whether it is appropriate for the expression to
  2161  // be freely duplicated.
  2162  //
  2163  // Given the declaration
  2164  //
  2165  //	func f(x T) T { return x + g() + x }
  2166  //
  2167  // an argument y is considered duplicable if we would wish to see a
  2168  // call f(y) simplified to y+g()+y. This is true for identifiers,
  2169  // integer literals, unary negation, and selectors x.f where x is not
  2170  // a pointer. But we would not wish to duplicate expressions that:
  2171  // - have side effects (e.g. nearly all calls),
  2172  // - are not referentially transparent (e.g. &T{}, ptr.field, *ptr), or
  2173  // - are long (e.g. "huge string literal").
  2174  func duplicable(info *types.Info, e ast.Expr) bool {
  2175  	switch e := e.(type) {
  2176  	case *ast.ParenExpr:
  2177  		return duplicable(info, e.X)
  2178  
  2179  	case *ast.Ident:
  2180  		return true
  2181  
  2182  	case *ast.BasicLit:
  2183  		v := info.Types[e].Value
  2184  		switch e.Kind {
  2185  		case token.INT:
  2186  			return true // any int
  2187  		case token.STRING:
  2188  			return consteq(v, kZeroString) // only ""
  2189  		case token.FLOAT:
  2190  			return consteq(v, kZeroFloat) || consteq(v, kOneFloat) // only 0.0 or 1.0
  2191  		}
  2192  
  2193  	case *ast.UnaryExpr: // e.g. +1, -1
  2194  		return (e.Op == token.ADD || e.Op == token.SUB) && duplicable(info, e.X)
  2195  
  2196  	case *ast.CompositeLit:
  2197  		// Empty struct or array literals T{} are duplicable.
  2198  		// (Non-empty literals are too verbose, and slice/map
  2199  		// literals allocate indirect variables.)
  2200  		if len(e.Elts) == 0 {
  2201  			switch info.TypeOf(e).Underlying().(type) {
  2202  			case *types.Struct, *types.Array:
  2203  				return true
  2204  			}
  2205  		}
  2206  		return false
  2207  
  2208  	case *ast.CallExpr:
  2209  		// Don't treat a conversion T(x) as duplicable even
  2210  		// if x is duplicable because it could duplicate
  2211  		// allocations.
  2212  		//
  2213  		// TODO(adonovan): there are cases to tease apart here:
  2214  		// duplicating string([]byte) conversions increases
  2215  		// allocation but doesn't change behavior, but the
  2216  		// reverse, []byte(string), allocates a distinct array,
  2217  		// which is observable
  2218  		return false
  2219  
  2220  	case *ast.SelectorExpr:
  2221  		if seln, ok := info.Selections[e]; ok {
  2222  			// A field or method selection x.f is referentially
  2223  			// transparent if it does not indirect a pointer.
  2224  			return !indirectSelection(seln)
  2225  		}
  2226  		// A qualified identifier pkg.Name is referentially transparent.
  2227  		return true
  2228  	}
  2229  	return false
  2230  }
  2231  
  2232  func consteq(x, y constant.Value) bool {
  2233  	return constant.Compare(x, token.EQL, y)
  2234  }
  2235  
  2236  var (
  2237  	kZeroInt    = constant.MakeInt64(0)
  2238  	kZeroString = constant.MakeString("")
  2239  	kZeroFloat  = constant.MakeFloat64(0.0)
  2240  	kOneFloat   = constant.MakeFloat64(1.0)
  2241  )
  2242  
  2243  // -- inline helpers --
  2244  
  2245  func assert(cond bool, msg string) {
  2246  	if !cond {
  2247  		panic(msg)
  2248  	}
  2249  }
  2250  
  2251  // blanks returns a slice of n > 0 blank identifiers.
  2252  func blanks[E ast.Expr](n int) []E {
  2253  	if n == 0 {
  2254  		panic("blanks(0)")
  2255  	}
  2256  	res := make([]E, n)
  2257  	for i := range res {
  2258  		res[i] = ast.Expr(makeIdent("_")).(E) // ugh
  2259  	}
  2260  	return res
  2261  }
  2262  
  2263  func makeIdent(name string) *ast.Ident {
  2264  	return &ast.Ident{Name: name}
  2265  }
  2266  
  2267  // importedPkgName returns the PkgName object declared by an ImportSpec.
  2268  // TODO(adonovan): make this a method of types.Info (#62037).
  2269  func importedPkgName(info *types.Info, imp *ast.ImportSpec) (*types.PkgName, bool) {
  2270  	var obj types.Object
  2271  	if imp.Name != nil {
  2272  		obj = info.Defs[imp.Name]
  2273  	} else {
  2274  		obj = info.Implicits[imp]
  2275  	}
  2276  	pkgname, ok := obj.(*types.PkgName)
  2277  	return pkgname, ok
  2278  }
  2279  
  2280  func isPkgLevel(obj types.Object) bool {
  2281  	// TODO(adonovan): consider using the simpler obj.Parent() ==
  2282  	// obj.Pkg().Scope() instead. But be sure to test carefully
  2283  	// with instantiations of generics.
  2284  	return obj.Pkg().Scope().Lookup(obj.Name()) == obj
  2285  }
  2286  
  2287  // callContext returns the two nodes immediately enclosing the call
  2288  // (specified as a PathEnclosingInterval), ignoring parens.
  2289  func callContext(callPath []ast.Node) (parent, grandparent ast.Node) {
  2290  	_ = callPath[0].(*ast.CallExpr) // sanity check
  2291  	for _, n := range callPath[1:] {
  2292  		if !is[*ast.ParenExpr](n) {
  2293  			if parent == nil {
  2294  				parent = n
  2295  			} else {
  2296  				return parent, n
  2297  			}
  2298  		}
  2299  	}
  2300  	return parent, nil
  2301  }
  2302  
  2303  // hasLabelConflict reports whether the set of labels of the function
  2304  // enclosing the call (specified as a PathEnclosingInterval)
  2305  // intersects with the set of callee labels.
  2306  func hasLabelConflict(callPath []ast.Node, calleeLabels []string) bool {
  2307  	labels := callerLabels(callPath)
  2308  	for _, label := range calleeLabels {
  2309  		if labels[label] {
  2310  			return true // conflict
  2311  		}
  2312  	}
  2313  	return false
  2314  }
  2315  
  2316  // callerLabels returns the set of control labels in the function (if
  2317  // any) enclosing the call (specified as a PathEnclosingInterval).
  2318  func callerLabels(callPath []ast.Node) map[string]bool {
  2319  	var callerBody *ast.BlockStmt
  2320  	switch f := callerFunc(callPath).(type) {
  2321  	case *ast.FuncDecl:
  2322  		callerBody = f.Body
  2323  	case *ast.FuncLit:
  2324  		callerBody = f.Body
  2325  	}
  2326  	var labels map[string]bool
  2327  	if callerBody != nil {
  2328  		ast.Inspect(callerBody, func(n ast.Node) bool {
  2329  			switch n := n.(type) {
  2330  			case *ast.FuncLit:
  2331  				return false // prune traversal
  2332  			case *ast.LabeledStmt:
  2333  				if labels == nil {
  2334  					labels = make(map[string]bool)
  2335  				}
  2336  				labels[n.Label.Name] = true
  2337  			}
  2338  			return true
  2339  		})
  2340  	}
  2341  	return labels
  2342  }
  2343  
  2344  // callerFunc returns the innermost Func{Decl,Lit} node enclosing the
  2345  // call (specified as a PathEnclosingInterval).
  2346  func callerFunc(callPath []ast.Node) ast.Node {
  2347  	_ = callPath[0].(*ast.CallExpr) // sanity check
  2348  	for _, n := range callPath[1:] {
  2349  		if is[*ast.FuncDecl](n) || is[*ast.FuncLit](n) {
  2350  			return n
  2351  		}
  2352  	}
  2353  	return nil
  2354  }
  2355  
  2356  // callStmt reports whether the function call (specified
  2357  // as a PathEnclosingInterval) appears within an ExprStmt,
  2358  // and returns it if so.
  2359  //
  2360  // If unrestricted, callStmt returns nil if the ExprStmt f() appears
  2361  // in a restricted context (such as "if f(); cond {") where it cannot
  2362  // be replaced by an arbitrary statement. (See "statement theory".)
  2363  func callStmt(callPath []ast.Node, unrestricted bool) *ast.ExprStmt {
  2364  	parent, _ := callContext(callPath)
  2365  	stmt, ok := parent.(*ast.ExprStmt)
  2366  	if ok && unrestricted {
  2367  		switch callPath[nodeIndex(callPath, stmt)+1].(type) {
  2368  		case *ast.LabeledStmt,
  2369  			*ast.BlockStmt,
  2370  			*ast.CaseClause,
  2371  			*ast.CommClause:
  2372  			// unrestricted
  2373  		default:
  2374  			// TODO(adonovan): handle restricted
  2375  			// XYZStmt.Init contexts (but not ForStmt.Post)
  2376  			// by creating a block around the if/for/switch:
  2377  			// "if f(); cond {"  ->  "{ stmts; if cond {"
  2378  
  2379  			return nil // restricted
  2380  		}
  2381  	}
  2382  	return stmt
  2383  }
  2384  
  2385  // Statement theory
  2386  //
  2387  // These are all the places a statement may appear in the AST:
  2388  //
  2389  // LabeledStmt.Stmt       Stmt      -- any
  2390  // BlockStmt.List       []Stmt      -- any (but see switch/select)
  2391  // IfStmt.Init            Stmt?     -- simple
  2392  // IfStmt.Body            BlockStmt
  2393  // IfStmt.Else            Stmt?     -- IfStmt or BlockStmt
  2394  // CaseClause.Body      []Stmt      -- any
  2395  // SwitchStmt.Init        Stmt?     -- simple
  2396  // SwitchStmt.Body        BlockStmt -- CaseClauses only
  2397  // TypeSwitchStmt.Init    Stmt?     -- simple
  2398  // TypeSwitchStmt.Assign  Stmt      -- AssignStmt(TypeAssertExpr) or ExprStmt(TypeAssertExpr)
  2399  // TypeSwitchStmt.Body    BlockStmt -- CaseClauses only
  2400  // CommClause.Comm        Stmt?     -- SendStmt or ExprStmt(UnaryExpr) or AssignStmt(UnaryExpr)
  2401  // CommClause.Body      []Stmt      -- any
  2402  // SelectStmt.Body        BlockStmt -- CommClauses only
  2403  // ForStmt.Init           Stmt?     -- simple
  2404  // ForStmt.Post           Stmt?     -- simple
  2405  // ForStmt.Body           BlockStmt
  2406  // RangeStmt.Body         BlockStmt
  2407  //
  2408  // simple = AssignStmt | SendStmt | IncDecStmt | ExprStmt.
  2409  //
  2410  // A BlockStmt cannot replace an ExprStmt in
  2411  // {If,Switch,TypeSwitch}Stmt.Init or ForStmt.Post.
  2412  // That is allowed only within:
  2413  //   LabeledStmt.Stmt       Stmt
  2414  //   BlockStmt.List       []Stmt
  2415  //   CaseClause.Body      []Stmt
  2416  //   CommClause.Body      []Stmt
  2417  
  2418  // replaceNode performs a destructive update of the tree rooted at
  2419  // root, replacing each occurrence of "from" with "to". If to is nil and
  2420  // the element is within a slice, the slice element is removed.
  2421  //
  2422  // The root itself cannot be replaced; an attempt will panic.
  2423  //
  2424  // This function must not be called on the caller's syntax tree.
  2425  //
  2426  // TODO(adonovan): polish this up and move it to astutil package.
  2427  // TODO(adonovan): needs a unit test.
  2428  func replaceNode(root ast.Node, from, to ast.Node) {
  2429  	if from == nil {
  2430  		panic("from == nil")
  2431  	}
  2432  	if reflect.ValueOf(from).IsNil() {
  2433  		panic(fmt.Sprintf("from == (%T)(nil)", from))
  2434  	}
  2435  	if from == root {
  2436  		panic("from == root")
  2437  	}
  2438  	found := false
  2439  	var parent reflect.Value // parent variable of interface type, containing a pointer
  2440  	var visit func(reflect.Value)
  2441  	visit = func(v reflect.Value) {
  2442  		switch v.Kind() {
  2443  		case reflect.Ptr:
  2444  			if v.Interface() == from {
  2445  				found = true
  2446  
  2447  				// If v is a struct field or array element
  2448  				// (e.g. Field.Comment or Field.Names[i])
  2449  				// then it is addressable (a pointer variable).
  2450  				//
  2451  				// But if it was the value an interface
  2452  				// (e.g. *ast.Ident within ast.Node)
  2453  				// then it is non-addressable, and we need
  2454  				// to set the enclosing interface (parent).
  2455  				if !v.CanAddr() {
  2456  					v = parent
  2457  				}
  2458  
  2459  				// to=nil => use zero value
  2460  				var toV reflect.Value
  2461  				if to != nil {
  2462  					toV = reflect.ValueOf(to)
  2463  				} else {
  2464  					toV = reflect.Zero(v.Type()) // e.g. ast.Expr(nil)
  2465  				}
  2466  				v.Set(toV)
  2467  
  2468  			} else if !v.IsNil() {
  2469  				switch v.Interface().(type) {
  2470  				case *ast.Object, *ast.Scope:
  2471  					// Skip fields of types potentially involved in cycles.
  2472  				default:
  2473  					visit(v.Elem())
  2474  				}
  2475  			}
  2476  
  2477  		case reflect.Struct:
  2478  			for i := 0; i < v.Type().NumField(); i++ {
  2479  				visit(v.Field(i))
  2480  			}
  2481  
  2482  		case reflect.Slice:
  2483  			compact := false
  2484  			for i := 0; i < v.Len(); i++ {
  2485  				visit(v.Index(i))
  2486  				if v.Index(i).IsNil() {
  2487  					compact = true
  2488  				}
  2489  			}
  2490  			if compact {
  2491  				// Elements were deleted. Eliminate nils.
  2492  				// (Do this is a second pass to avoid
  2493  				// unnecessary writes in the common case.)
  2494  				j := 0
  2495  				for i := 0; i < v.Len(); i++ {
  2496  					if !v.Index(i).IsNil() {
  2497  						v.Index(j).Set(v.Index(i))
  2498  						j++
  2499  					}
  2500  				}
  2501  				v.SetLen(j)
  2502  			}
  2503  		case reflect.Interface:
  2504  			parent = v
  2505  			visit(v.Elem())
  2506  
  2507  		case reflect.Array, reflect.Chan, reflect.Func, reflect.Map, reflect.UnsafePointer:
  2508  			panic(v) // unreachable in AST
  2509  		default:
  2510  			// bool, string, number: nop
  2511  		}
  2512  		parent = reflect.Value{}
  2513  	}
  2514  	visit(reflect.ValueOf(root))
  2515  	if !found {
  2516  		panic(fmt.Sprintf("%T not found", from))
  2517  	}
  2518  }
  2519  
  2520  // clearPositions destroys token.Pos information within the tree rooted at root,
  2521  // as positions in callee trees may cause caller comments to be emitted prematurely.
  2522  //
  2523  // In general it isn't safe to clear a valid Pos because some of them
  2524  // (e.g. CallExpr.Ellipsis, TypeSpec.Assign) are significant to
  2525  // go/printer, so this function sets each non-zero Pos to 1, which
  2526  // suffices to avoid advancing the printer's comment cursor.
  2527  //
  2528  // This function mutates its argument; do not invoke on caller syntax.
  2529  //
  2530  // TODO(adonovan): remove this horrendous workaround when #20744 is finally fixed.
  2531  func clearPositions(root ast.Node) {
  2532  	posType := reflect.TypeOf(token.NoPos)
  2533  	ast.Inspect(root, func(n ast.Node) bool {
  2534  		if n != nil {
  2535  			v := reflect.ValueOf(n).Elem() // deref the pointer to struct
  2536  			fields := v.Type().NumField()
  2537  			for i := 0; i < fields; i++ {
  2538  				f := v.Field(i)
  2539  				// Clearing Pos arbitrarily is destructive,
  2540  				// as its presence may be semantically significant
  2541  				// (e.g. CallExpr.Ellipsis, TypeSpec.Assign)
  2542  				// or affect formatting preferences (e.g. GenDecl.Lparen).
  2543  				//
  2544  				// Note: for proper formatting, it may be necessary to be selective
  2545  				// about which positions we set to 1 vs which we set to token.NoPos.
  2546  				// (e.g. we can set most to token.NoPos, save the few that are
  2547  				// significant).
  2548  				if f.Type() == posType {
  2549  					if f.Interface() != token.NoPos {
  2550  						f.Set(reflect.ValueOf(token.Pos(1)))
  2551  					}
  2552  				}
  2553  			}
  2554  		}
  2555  		return true
  2556  	})
  2557  }
  2558  
  2559  // findIdent returns the Ident beneath root that has the given pos.
  2560  func findIdent(root ast.Node, pos token.Pos) *ast.Ident {
  2561  	// TODO(adonovan): opt: skip subtrees that don't contain pos.
  2562  	var found *ast.Ident
  2563  	ast.Inspect(root, func(n ast.Node) bool {
  2564  		if found != nil {
  2565  			return false
  2566  		}
  2567  		if id, ok := n.(*ast.Ident); ok {
  2568  			if id.Pos() == pos {
  2569  				found = id
  2570  			}
  2571  		}
  2572  		return true
  2573  	})
  2574  	if found == nil {
  2575  		panic(fmt.Sprintf("findIdent %d not found in %s",
  2576  			pos, debugFormatNode(token.NewFileSet(), root)))
  2577  	}
  2578  	return found
  2579  }
  2580  
  2581  func prepend[T any](elem T, slice ...T) []T {
  2582  	return append([]T{elem}, slice...)
  2583  }
  2584  
  2585  // debugFormatNode formats a node or returns a formatting error.
  2586  // Its sloppy treatment of errors is appropriate only for logging.
  2587  func debugFormatNode(fset *token.FileSet, n ast.Node) string {
  2588  	var out strings.Builder
  2589  	if err := format.Node(&out, fset, n); err != nil {
  2590  		out.WriteString(err.Error())
  2591  	}
  2592  	return out.String()
  2593  }
  2594  
  2595  func shallowCopy[T any](ptr *T) *T {
  2596  	copy := *ptr
  2597  	return &copy
  2598  }
  2599  
  2600  // ∀
  2601  func forall[T any](list []T, f func(i int, x T) bool) bool {
  2602  	for i, x := range list {
  2603  		if !f(i, x) {
  2604  			return false
  2605  		}
  2606  	}
  2607  	return true
  2608  }
  2609  
  2610  // ∃
  2611  func exists[T any](list []T, f func(i int, x T) bool) bool {
  2612  	for i, x := range list {
  2613  		if f(i, x) {
  2614  			return true
  2615  		}
  2616  	}
  2617  	return false
  2618  }
  2619  
  2620  // last returns the last element of a slice, or zero if empty.
  2621  func last[T any](slice []T) T {
  2622  	n := len(slice)
  2623  	if n > 0 {
  2624  		return slice[n-1]
  2625  	}
  2626  	return *new(T)
  2627  }
  2628  
  2629  // canImport reports whether one package is allowed to import another.
  2630  //
  2631  // TODO(adonovan): allow customization of the accessibility relation
  2632  // (e.g. for Bazel).
  2633  func canImport(from, to string) bool {
  2634  	// TODO(adonovan): better segment hygiene.
  2635  	if strings.HasPrefix(to, "internal/") {
  2636  		// Special case: only std packages may import internal/...
  2637  		// We can't reliably know whether we're in std, so we
  2638  		// use a heuristic on the first segment.
  2639  		first, _, _ := strings.Cut(from, "/")
  2640  		if strings.Contains(first, ".") {
  2641  			return false // example.com/foo ∉ std
  2642  		}
  2643  		if first == "testdata" {
  2644  			return false // testdata/foo ∉ std
  2645  		}
  2646  	}
  2647  	if i := strings.LastIndex(to, "/internal/"); i >= 0 {
  2648  		return strings.HasPrefix(from, to[:i])
  2649  	}
  2650  	return true
  2651  }
  2652  
  2653  // consistentOffsets reports whether the portion of caller.Content
  2654  // that corresponds to caller.Call can be parsed as a call expression.
  2655  // If not, the client has provided inconsistent information, possibly
  2656  // because they forgot to ignore line directives when computing the
  2657  // filename enclosing the call.
  2658  // This is just a heuristic.
  2659  func consistentOffsets(caller *Caller) bool {
  2660  	start := offsetOf(caller.Fset, caller.Call.Pos())
  2661  	end := offsetOf(caller.Fset, caller.Call.End())
  2662  	if !(0 < start && start < end && end <= len(caller.Content)) {
  2663  		return false
  2664  	}
  2665  	expr, err := parser.ParseExpr(string(caller.Content[start:end]))
  2666  	if err != nil {
  2667  		return false
  2668  	}
  2669  	return is[*ast.CallExpr](expr)
  2670  }
  2671  
  2672  // needsParens reports whether parens are required to avoid ambiguity
  2673  // around the new node replacing the specified old node (which is some
  2674  // ancestor of the CallExpr identified by its PathEnclosingInterval).
  2675  func needsParens(callPath []ast.Node, old, new ast.Node) bool {
  2676  	// Find enclosing old node and its parent.
  2677  	i := nodeIndex(callPath, old)
  2678  	if i == -1 {
  2679  		panic("not found")
  2680  	}
  2681  
  2682  	// There is no precedence ambiguity when replacing
  2683  	// (e.g.) a statement enclosing the call.
  2684  	if !is[ast.Expr](old) {
  2685  		return false
  2686  	}
  2687  
  2688  	// An expression beneath a non-expression
  2689  	// has no precedence ambiguity.
  2690  	parent, ok := callPath[i+1].(ast.Expr)
  2691  	if !ok {
  2692  		return false
  2693  	}
  2694  
  2695  	precedence := func(n ast.Node) int {
  2696  		switch n := n.(type) {
  2697  		case *ast.UnaryExpr, *ast.StarExpr:
  2698  			return token.UnaryPrec
  2699  		case *ast.BinaryExpr:
  2700  			return n.Op.Precedence()
  2701  		}
  2702  		return -1
  2703  	}
  2704  
  2705  	// Parens are not required if the new node
  2706  	// is not unary or binary.
  2707  	newprec := precedence(new)
  2708  	if newprec < 0 {
  2709  		return false
  2710  	}
  2711  
  2712  	// Parens are required if parent and child are both
  2713  	// unary or binary and the parent has higher precedence.
  2714  	if precedence(parent) > newprec {
  2715  		return true
  2716  	}
  2717  
  2718  	// Was the old node the operand of a postfix operator?
  2719  	//  f().sel
  2720  	//  f()[i:j]
  2721  	//  f()[i]
  2722  	//  f().(T)
  2723  	//  f()(x)
  2724  	switch parent := parent.(type) {
  2725  	case *ast.SelectorExpr:
  2726  		return parent.X == old
  2727  	case *ast.IndexExpr:
  2728  		return parent.X == old
  2729  	case *ast.SliceExpr:
  2730  		return parent.X == old
  2731  	case *ast.TypeAssertExpr:
  2732  		return parent.X == old
  2733  	case *ast.CallExpr:
  2734  		return parent.Fun == old
  2735  	}
  2736  	return false
  2737  }
  2738  
  2739  func nodeIndex(nodes []ast.Node, n ast.Node) int {
  2740  	// TODO(adonovan): Use index[ast.Node]() in go1.20.
  2741  	for i, node := range nodes {
  2742  		if node == n {
  2743  			return i
  2744  		}
  2745  	}
  2746  	return -1
  2747  }
  2748  
  2749  // declares returns the set of lexical names declared by a
  2750  // sequence of statements from the same block, excluding sub-blocks.
  2751  // (Lexical names do not include control labels.)
  2752  func declares(stmts []ast.Stmt) map[string]bool {
  2753  	names := make(map[string]bool)
  2754  	for _, stmt := range stmts {
  2755  		switch stmt := stmt.(type) {
  2756  		case *ast.DeclStmt:
  2757  			for _, spec := range stmt.Decl.(*ast.GenDecl).Specs {
  2758  				switch spec := spec.(type) {
  2759  				case *ast.ValueSpec:
  2760  					for _, id := range spec.Names {
  2761  						names[id.Name] = true
  2762  					}
  2763  				case *ast.TypeSpec:
  2764  					names[spec.Name.Name] = true
  2765  				}
  2766  			}
  2767  
  2768  		case *ast.AssignStmt:
  2769  			if stmt.Tok == token.DEFINE {
  2770  				for _, lhs := range stmt.Lhs {
  2771  					names[lhs.(*ast.Ident).Name] = true
  2772  				}
  2773  			}
  2774  		}
  2775  	}
  2776  	delete(names, "_")
  2777  	return names
  2778  }
  2779  
  2780  // assignStmts rewrites a statement assigning the results of a call into zero
  2781  // or more statements that assign its return operands, or (nil, false) if no
  2782  // such rewrite is possible. The set of bindings created by the result of
  2783  // assignStmts is the same as the set of bindings created by the callerStmt.
  2784  //
  2785  // The callee must contain exactly one return statement.
  2786  //
  2787  // This is (once again) a surprisingly complex task. For example, depending on
  2788  // types and existing bindings, the assignment
  2789  //
  2790  //	a, b := f()
  2791  //
  2792  // could be rewritten as:
  2793  //
  2794  //	a, b := 1, 2
  2795  //
  2796  // but may need to be written as:
  2797  //
  2798  //	a, b := int8(1), int32(2)
  2799  //
  2800  // In the case where the return statement within f is a spread call to another
  2801  // function g(), we cannot explicitly convert the return values inline, and so
  2802  // it may be necessary to split the declaration and assignment of variables
  2803  // into separate statements:
  2804  //
  2805  //	a, b := g()
  2806  //
  2807  // or
  2808  //
  2809  //	var a int32
  2810  //	a, b = g()
  2811  //
  2812  // or
  2813  //
  2814  //	var (
  2815  //		a int8
  2816  //		b int32
  2817  //	)
  2818  //	a, b = g()
  2819  //
  2820  // Note: assignStmts may return (nil, true) if it determines that the rewritten
  2821  // assignment consists only of _ = nil assignments.
  2822  func (st *state) assignStmts(callerStmt *ast.AssignStmt, returnOperands []ast.Expr) ([]ast.Stmt, bool) {
  2823  	logf, caller, callee := st.opts.Logf, st.caller, &st.callee.impl
  2824  
  2825  	assert(len(callee.Returns) == 1, "unexpected multiple returns")
  2826  	resultInfo := callee.Returns[0]
  2827  
  2828  	// When constructing assign statements, we need to make sure that we don't
  2829  	// modify types on the left-hand side, such as would happen if the type of a
  2830  	// RHS expression does not match the corresponding LHS type at the caller
  2831  	// (due to untyped conversion or interface widening).
  2832  	//
  2833  	// This turns out to be remarkably tricky to handle correctly.
  2834  	//
  2835  	// Substrategies below are labeled as `Substrategy <name>:`.
  2836  
  2837  	// Collect LHS information.
  2838  	var (
  2839  		lhs    []ast.Expr                                // shallow copy of the LHS slice, for mutation
  2840  		defs   = make([]*ast.Ident, len(callerStmt.Lhs)) // indexes in lhs of defining identifiers
  2841  		blanks = make([]bool, len(callerStmt.Lhs))       // indexes in lhs of blank identifiers
  2842  		byType typeutil.Map                              // map of distinct types -> indexes, for writing specs later
  2843  	)
  2844  	for i, expr := range callerStmt.Lhs {
  2845  		lhs = append(lhs, expr)
  2846  		if name, ok := expr.(*ast.Ident); ok {
  2847  			if name.Name == "_" {
  2848  				blanks[i] = true
  2849  				continue // no type
  2850  			}
  2851  
  2852  			if obj, isDef := caller.Info.Defs[name]; isDef {
  2853  				defs[i] = name
  2854  				typ := obj.Type()
  2855  				idxs, _ := byType.At(typ).([]int)
  2856  				idxs = append(idxs, i)
  2857  				byType.Set(typ, idxs)
  2858  			}
  2859  		}
  2860  	}
  2861  
  2862  	// Collect RHS information
  2863  	//
  2864  	// The RHS is either a parallel assignment or spread assignment, but by
  2865  	// looping over both callerStmt.Rhs and returnOperands we handle both.
  2866  	var (
  2867  		rhs             []ast.Expr              // new RHS of assignment, owned by the inliner
  2868  		callIdx         = -1                    // index of the call among the original RHS
  2869  		nilBlankAssigns = make(map[int]unit)    // indexes in rhs of _ = nil assignments, which can be deleted
  2870  		freeNames       = make(map[string]bool) // free(ish) names among rhs expressions
  2871  		nonTrivial      = make(map[int]bool)    // indexes in rhs of nontrivial result conversions
  2872  	)
  2873  	for i, expr := range callerStmt.Rhs {
  2874  		if expr == caller.Call {
  2875  			assert(callIdx == -1, "malformed (duplicative) AST")
  2876  			callIdx = i
  2877  			for j, returnOperand := range returnOperands {
  2878  				freeishNames(freeNames, returnOperand)
  2879  				rhs = append(rhs, returnOperand)
  2880  				if resultInfo[j]&nonTrivialResult != 0 {
  2881  					nonTrivial[i+j] = true
  2882  				}
  2883  				if blanks[i+j] && resultInfo[j]&untypedNilResult != 0 {
  2884  					nilBlankAssigns[i+j] = unit{}
  2885  				}
  2886  			}
  2887  		} else {
  2888  			// We must clone before clearing positions, since e came from the caller.
  2889  			expr = internalastutil.CloneNode(expr)
  2890  			clearPositions(expr)
  2891  			freeishNames(freeNames, expr)
  2892  			rhs = append(rhs, expr)
  2893  		}
  2894  	}
  2895  	assert(callIdx >= 0, "failed to find call in RHS")
  2896  
  2897  	// Substrategy "splice": Check to see if we can simply splice in the result
  2898  	// expressions from the callee, such as simplifying
  2899  	//
  2900  	//  x, y := f()
  2901  	//
  2902  	// to
  2903  	//
  2904  	//  x, y := e1, e2
  2905  	//
  2906  	// where the types of x and y match the types of e1 and e2.
  2907  	//
  2908  	// This works as long as we don't need to write any additional type
  2909  	// information.
  2910  	if callerStmt.Tok == token.ASSIGN && // LHS types already determined before call
  2911  		len(nonTrivial) == 0 { // no non-trivial conversions to worry about
  2912  
  2913  		logf("substrategy: slice assignment")
  2914  		return []ast.Stmt{&ast.AssignStmt{
  2915  			Lhs:    lhs,
  2916  			Tok:    callerStmt.Tok,
  2917  			TokPos: callerStmt.TokPos,
  2918  			Rhs:    rhs,
  2919  		}}, true
  2920  	}
  2921  
  2922  	// Inlining techniques below will need to write type information in order to
  2923  	// preserve the correct types of LHS identifiers.
  2924  	//
  2925  	// writeType is a simple helper to write out type expressions.
  2926  	// TODO(rfindley):
  2927  	//   1. handle qualified type names (potentially adding new imports)
  2928  	//   2. expand this to handle more type expressions.
  2929  	//   3. refactor to share logic with callee rewriting.
  2930  	universeAny := types.Universe.Lookup("any")
  2931  	typeExpr := func(typ types.Type, shadows ...map[string]bool) ast.Expr {
  2932  		var typeName string
  2933  		switch typ := typ.(type) {
  2934  		case *types.Basic:
  2935  			typeName = typ.Name()
  2936  		case interface{ Obj() *types.TypeName }: // Named, Alias, TypeParam
  2937  			typeName = typ.Obj().Name()
  2938  		}
  2939  
  2940  		// Special case: check for universe "any".
  2941  		// TODO(golang/go#66921): this may become unnecessary if any becomes a proper alias.
  2942  		if typ == universeAny.Type() {
  2943  			typeName = "any"
  2944  		}
  2945  
  2946  		if typeName == "" {
  2947  			return nil
  2948  		}
  2949  
  2950  		for _, shadow := range shadows {
  2951  			if shadow[typeName] {
  2952  				logf("cannot write shadowed type name %q", typeName)
  2953  				return nil
  2954  			}
  2955  		}
  2956  		obj, _ := caller.lookup(typeName).(*types.TypeName)
  2957  		if obj != nil && types.Identical(obj.Type(), typ) {
  2958  			return ast.NewIdent(typeName)
  2959  		}
  2960  		return nil
  2961  	}
  2962  
  2963  	// Substrategy "spread": in the case of a spread call (func f() (T1, T2) return
  2964  	// g()), since we didn't hit the 'splice' substrategy, there must be some
  2965  	// non-declaring expression on the LHS. Simplify this by pre-declaring
  2966  	// variables, rewriting
  2967  	//
  2968  	//   x, y := f()
  2969  	//
  2970  	// to
  2971  	//
  2972  	//  var x int
  2973  	//  x, y = g()
  2974  	//
  2975  	// Which works as long as the predeclared variables do not overlap with free
  2976  	// names on the RHS.
  2977  	if len(rhs) != len(lhs) {
  2978  		assert(len(rhs) == 1 && len(returnOperands) == 1, "expected spread call")
  2979  
  2980  		for _, id := range defs {
  2981  			if id != nil && freeNames[id.Name] {
  2982  				// By predeclaring variables, we're changing them to be in scope of the
  2983  				// RHS. We can't do this if their names are free on the RHS.
  2984  				return nil, false
  2985  			}
  2986  		}
  2987  
  2988  		// Write out the specs, being careful to avoid shadowing free names in
  2989  		// their type expressions.
  2990  		var (
  2991  			specs    []ast.Spec
  2992  			specIdxs []int
  2993  			shadow   = make(map[string]bool)
  2994  		)
  2995  		failed := false
  2996  		byType.Iterate(func(typ types.Type, v any) {
  2997  			if failed {
  2998  				return
  2999  			}
  3000  			idxs := v.([]int)
  3001  			specIdxs = append(specIdxs, idxs[0])
  3002  			texpr := typeExpr(typ, shadow)
  3003  			if texpr == nil {
  3004  				failed = true
  3005  				return
  3006  			}
  3007  			spec := &ast.ValueSpec{
  3008  				Type: texpr,
  3009  			}
  3010  			for _, idx := range idxs {
  3011  				spec.Names = append(spec.Names, ast.NewIdent(defs[idx].Name))
  3012  			}
  3013  			specs = append(specs, spec)
  3014  		})
  3015  		if failed {
  3016  			return nil, false
  3017  		}
  3018  		logf("substrategy: spread assignment")
  3019  		return []ast.Stmt{
  3020  			&ast.DeclStmt{
  3021  				Decl: &ast.GenDecl{
  3022  					Tok:   token.VAR,
  3023  					Specs: specs,
  3024  				},
  3025  			},
  3026  			&ast.AssignStmt{
  3027  				Lhs: callerStmt.Lhs,
  3028  				Tok: token.ASSIGN,
  3029  				Rhs: returnOperands,
  3030  			},
  3031  		}, true
  3032  	}
  3033  
  3034  	assert(len(lhs) == len(rhs), "mismatching LHS and RHS")
  3035  
  3036  	// Substrategy "convert": write out RHS expressions with explicit type conversions
  3037  	// as necessary, rewriting
  3038  	//
  3039  	//  x, y := f()
  3040  	//
  3041  	// to
  3042  	//
  3043  	//  x, y := 1, int32(2)
  3044  	//
  3045  	// As required to preserve types.
  3046  	//
  3047  	// In the special case of _ = nil, which is disallowed by the type checker
  3048  	// (since nil has no default type), we delete the assignment.
  3049  	var origIdxs []int // maps back to original indexes after lhs and rhs are pruned
  3050  	i := 0
  3051  	for j := range lhs {
  3052  		if _, ok := nilBlankAssigns[j]; !ok {
  3053  			lhs[i] = lhs[j]
  3054  			rhs[i] = rhs[j]
  3055  			origIdxs = append(origIdxs, j)
  3056  			i++
  3057  		}
  3058  	}
  3059  	lhs = lhs[:i]
  3060  	rhs = rhs[:i]
  3061  
  3062  	if len(lhs) == 0 {
  3063  		logf("trivial assignment after pruning nil blanks assigns")
  3064  		// After pruning, we have no remaining assignments.
  3065  		// Signal this by returning a non-nil slice of statements.
  3066  		return nil, true
  3067  	}
  3068  
  3069  	// Write out explicit conversions as necessary.
  3070  	//
  3071  	// A conversion is necessary if the LHS is being defined, and the RHS return
  3072  	// involved a nontrivial implicit conversion.
  3073  	for i, expr := range rhs {
  3074  		idx := origIdxs[i]
  3075  		if nonTrivial[idx] && defs[idx] != nil {
  3076  			typ := caller.Info.TypeOf(lhs[i])
  3077  			texpr := typeExpr(typ)
  3078  			if texpr == nil {
  3079  				return nil, false
  3080  			}
  3081  			if _, ok := texpr.(*ast.StarExpr); ok {
  3082  				// TODO(rfindley): is this necessary? Doesn't the formatter add these parens?
  3083  				texpr = &ast.ParenExpr{X: texpr} // *T -> (*T)   so that (*T)(x) is valid
  3084  			}
  3085  			rhs[i] = &ast.CallExpr{
  3086  				Fun:  texpr,
  3087  				Args: []ast.Expr{expr},
  3088  			}
  3089  		}
  3090  	}
  3091  	logf("substrategy: convert assignment")
  3092  	return []ast.Stmt{&ast.AssignStmt{
  3093  		Lhs: lhs,
  3094  		Tok: callerStmt.Tok,
  3095  		Rhs: rhs,
  3096  	}}, true
  3097  }
  3098  
  3099  // tailCallSafeReturn reports whether the callee's return statements may be safely
  3100  // used to return from the function enclosing the caller (which must exist).
  3101  func tailCallSafeReturn(caller *Caller, calleeSymbol *types.Func, callee *gobCallee) bool {
  3102  	// It is safe if all callee returns involve only trivial conversions.
  3103  	if !hasNonTrivialReturn(callee.Returns) {
  3104  		return true
  3105  	}
  3106  
  3107  	var callerType types.Type
  3108  	// Find type of innermost function enclosing call.
  3109  	// (Beware: Caller.enclosingFunc is the outermost.)
  3110  loop:
  3111  	for _, n := range caller.path {
  3112  		switch f := n.(type) {
  3113  		case *ast.FuncDecl:
  3114  			callerType = caller.Info.ObjectOf(f.Name).Type()
  3115  			break loop
  3116  		case *ast.FuncLit:
  3117  			callerType = caller.Info.TypeOf(f)
  3118  			break loop
  3119  		}
  3120  	}
  3121  
  3122  	// Non-trivial return conversions in the callee are permitted
  3123  	// if the same non-trivial conversion would occur after inlining,
  3124  	// i.e. if the caller and callee results tuples are identical.
  3125  	callerResults := callerType.(*types.Signature).Results()
  3126  	calleeResults := calleeSymbol.Type().(*types.Signature).Results()
  3127  	return types.Identical(callerResults, calleeResults)
  3128  }
  3129  
  3130  // hasNonTrivialReturn reports whether any of the returns involve a nontrivial
  3131  // implicit conversion of a result expression.
  3132  func hasNonTrivialReturn(returnInfo [][]returnOperandFlags) bool {
  3133  	for _, resultInfo := range returnInfo {
  3134  		for _, r := range resultInfo {
  3135  			if r&nonTrivialResult != 0 {
  3136  				return true
  3137  			}
  3138  		}
  3139  	}
  3140  	return false
  3141  }
  3142  
  3143  type unit struct{} // for representing sets as maps