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