golang.org/x/tools/gopls@v0.15.3/internal/golang/rename_check.go (about)

     1  // Copyright 2019 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  // Taken from golang.org/x/tools/refactor/rename.
     6  
     7  package golang
     8  
     9  // This file defines the conflict-checking portion of the rename operation.
    10  //
    11  // The renamer works on a single package of type-checked syntax, and
    12  // is called in parallel for all necessary packages in the workspace,
    13  // possibly up to the transitive reverse dependencies of the
    14  // declaration. Finally the union of all edits and errors is computed.
    15  //
    16  // Renaming one object may entail renaming of others. For example:
    17  //
    18  // - An embedded field couples a Var (field) and a TypeName.
    19  //   So, renaming either one requires renaming the other.
    20  //   If the initial object is an embedded field, we must add its
    21  //   TypeName (and its enclosing package) to the renaming set;
    22  //   this is easily discovered at the outset.
    23  //
    24  //   Conversely, if the initial object is a TypeName, we must observe
    25  //   whether any of its references (from directly importing packages)
    26  //   is coincident with an embedded field Var and, if so, initiate a
    27  //   renaming of it.
    28  //
    29  // - A method of an interface type is coupled to all corresponding
    30  //   methods of types that are assigned to the interface (as
    31  //   discovered by the 'satisfy' pass). As a matter of usability, we
    32  //   require that such renamings be initiated from the interface
    33  //   method, not the concrete method.
    34  
    35  import (
    36  	"fmt"
    37  	"go/ast"
    38  	"go/token"
    39  	"go/types"
    40  	"path/filepath"
    41  	"reflect"
    42  	"strings"
    43  	"unicode"
    44  
    45  	"golang.org/x/tools/go/ast/astutil"
    46  	"golang.org/x/tools/gopls/internal/cache"
    47  	"golang.org/x/tools/gopls/internal/util/safetoken"
    48  	"golang.org/x/tools/refactor/satisfy"
    49  )
    50  
    51  // errorf reports an error (e.g. conflict) and prevents file modification.
    52  func (r *renamer) errorf(pos token.Pos, format string, args ...interface{}) {
    53  	// Conflict error messages in the old gorename tool (whence this
    54  	// logic originated) contain rich information associated with
    55  	// multiple source lines, such as:
    56  	//
    57  	//   p/a.go:1:2: renaming "x" to "y" here
    58  	//   p/b.go:3:4: \t would cause this reference to "y"
    59  	//   p/c.go:5:5: \t to become shadowed by this intervening declaration.
    60  	//
    61  	// Unfortunately LSP provides no means to transmit the
    62  	// structure of this error, so we format the positions briefly
    63  	// using dir/file.go where dir is the base name of the parent
    64  	// directory.
    65  
    66  	var conflict strings.Builder
    67  
    68  	// Add prefix of (truncated) position.
    69  	if pos != token.NoPos {
    70  		// TODO(adonovan): skip position of first error if it is
    71  		// on the same line as the renaming itself.
    72  		posn := safetoken.StartPosition(r.pkg.FileSet(), pos).String()
    73  		segments := strings.Split(filepath.ToSlash(posn), "/")
    74  		if n := len(segments); n > 2 {
    75  			segments = segments[n-2:]
    76  		}
    77  		posn = strings.Join(segments, "/")
    78  		fmt.Fprintf(&conflict, "%s:", posn)
    79  
    80  		if !strings.HasPrefix(format, "\t") {
    81  			conflict.WriteByte(' ')
    82  		}
    83  	}
    84  
    85  	fmt.Fprintf(&conflict, format, args...)
    86  	r.conflicts = append(r.conflicts, conflict.String())
    87  }
    88  
    89  // check performs safety checks of the renaming of the 'from' object to r.to.
    90  func (r *renamer) check(from types.Object) {
    91  	if r.objsToUpdate[from] {
    92  		return
    93  	}
    94  	r.objsToUpdate[from] = true
    95  
    96  	// NB: order of conditions is important.
    97  	if from_, ok := from.(*types.PkgName); ok {
    98  		r.checkInFileBlock(from_)
    99  	} else if from_, ok := from.(*types.Label); ok {
   100  		r.checkLabel(from_)
   101  	} else if isPackageLevel(from) {
   102  		r.checkInPackageBlock(from)
   103  	} else if v, ok := from.(*types.Var); ok && v.IsField() {
   104  		r.checkStructField(v)
   105  	} else if f, ok := from.(*types.Func); ok && recv(f) != nil {
   106  		r.checkMethod(f)
   107  	} else if isLocal(from) {
   108  		r.checkInLexicalScope(from)
   109  	} else {
   110  		r.errorf(from.Pos(), "unexpected %s object %q (please report a bug)\n",
   111  			objectKind(from), from)
   112  	}
   113  }
   114  
   115  // checkInFileBlock performs safety checks for renames of objects in the file block,
   116  // i.e. imported package names.
   117  func (r *renamer) checkInFileBlock(from *types.PkgName) {
   118  	// Check import name is not "init".
   119  	if r.to == "init" {
   120  		r.errorf(from.Pos(), "%q is not a valid imported package name", r.to)
   121  	}
   122  
   123  	// Check for conflicts between file and package block.
   124  	if prev := from.Pkg().Scope().Lookup(r.to); prev != nil {
   125  		r.errorf(from.Pos(), "renaming this %s %q to %q would conflict",
   126  			objectKind(from), from.Name(), r.to)
   127  		r.errorf(prev.Pos(), "\twith this package member %s",
   128  			objectKind(prev))
   129  		return // since checkInPackageBlock would report redundant errors
   130  	}
   131  
   132  	// Check for conflicts in lexical scope.
   133  	r.checkInLexicalScope(from)
   134  }
   135  
   136  // checkInPackageBlock performs safety checks for renames of
   137  // func/var/const/type objects in the package block.
   138  func (r *renamer) checkInPackageBlock(from types.Object) {
   139  	// Check that there are no references to the name from another
   140  	// package if the renaming would make it unexported.
   141  	if typ := r.pkg.GetTypes(); typ != from.Pkg() && ast.IsExported(r.from) && !ast.IsExported(r.to) {
   142  		if id := someUse(r.pkg.GetTypesInfo(), from); id != nil {
   143  			r.checkExport(id, typ, from)
   144  		}
   145  	}
   146  
   147  	// Check that in the package block, "init" is a function, and never referenced.
   148  	if r.to == "init" {
   149  		kind := objectKind(from)
   150  		if kind == "func" {
   151  			// Reject if intra-package references to it exist.
   152  			for id, obj := range r.pkg.GetTypesInfo().Uses {
   153  				if obj == from {
   154  					r.errorf(from.Pos(),
   155  						"renaming this func %q to %q would make it a package initializer",
   156  						from.Name(), r.to)
   157  					r.errorf(id.Pos(), "\tbut references to it exist")
   158  					break
   159  				}
   160  			}
   161  		} else {
   162  			r.errorf(from.Pos(), "you cannot have a %s at package level named %q",
   163  				kind, r.to)
   164  		}
   165  	}
   166  
   167  	// Check for conflicts between package block and all file blocks.
   168  	for _, f := range r.pkg.GetSyntax() {
   169  		fileScope := r.pkg.GetTypesInfo().Scopes[f]
   170  		b, prev := fileScope.LookupParent(r.to, token.NoPos)
   171  		if b == fileScope {
   172  			r.errorf(from.Pos(), "renaming this %s %q to %q would conflict", objectKind(from), from.Name(), r.to)
   173  			var prevPos token.Pos
   174  			if prev != nil {
   175  				prevPos = prev.Pos()
   176  			}
   177  			r.errorf(prevPos, "\twith this %s", objectKind(prev))
   178  			return // since checkInPackageBlock would report redundant errors
   179  		}
   180  	}
   181  
   182  	// Check for conflicts in lexical scope.
   183  	r.checkInLexicalScope(from)
   184  }
   185  
   186  // checkInLexicalScope performs safety checks that a renaming does not
   187  // change the lexical reference structure of the specified package.
   188  //
   189  // For objects in lexical scope, there are three kinds of conflicts:
   190  // same-, sub-, and super-block conflicts.  We will illustrate all three
   191  // using this example:
   192  //
   193  //	var x int
   194  //	var z int
   195  //
   196  //	func f(y int) {
   197  //		print(x)
   198  //		print(y)
   199  //	}
   200  //
   201  // Renaming x to z encounters a "same-block conflict", because an object
   202  // with the new name already exists, defined in the same lexical block
   203  // as the old object.
   204  //
   205  // Renaming x to y encounters a "sub-block conflict", because there exists
   206  // a reference to x from within (what would become) a hole in its scope.
   207  // The definition of y in an (inner) sub-block would cast a shadow in
   208  // the scope of the renamed variable.
   209  //
   210  // Renaming y to x encounters a "super-block conflict".  This is the
   211  // converse situation: there is an existing definition of the new name
   212  // (x) in an (enclosing) super-block, and the renaming would create a
   213  // hole in its scope, within which there exist references to it.  The
   214  // new name shadows the existing definition of x in the super-block.
   215  //
   216  // Removing the old name (and all references to it) is always safe, and
   217  // requires no checks.
   218  func (r *renamer) checkInLexicalScope(from types.Object) {
   219  	b := from.Parent() // the block defining the 'from' object
   220  	if b != nil {
   221  		toBlock, to := b.LookupParent(r.to, from.Parent().End())
   222  		if toBlock == b {
   223  			// same-block conflict
   224  			r.errorf(from.Pos(), "renaming this %s %q to %q",
   225  				objectKind(from), from.Name(), r.to)
   226  			r.errorf(to.Pos(), "\tconflicts with %s in same block",
   227  				objectKind(to))
   228  			return
   229  		} else if toBlock != nil {
   230  			// Check for super-block conflict.
   231  			// The name r.to is defined in a superblock.
   232  			// Is that name referenced from within this block?
   233  			forEachLexicalRef(r.pkg, to, func(id *ast.Ident, block *types.Scope) bool {
   234  				_, obj := block.LookupParent(from.Name(), id.Pos())
   235  				if obj == from {
   236  					// super-block conflict
   237  					r.errorf(from.Pos(), "renaming this %s %q to %q",
   238  						objectKind(from), from.Name(), r.to)
   239  					r.errorf(id.Pos(), "\twould shadow this reference")
   240  					r.errorf(to.Pos(), "\tto the %s declared here",
   241  						objectKind(to))
   242  					return false // stop
   243  				}
   244  				return true
   245  			})
   246  		}
   247  	}
   248  	// Check for sub-block conflict.
   249  	// Is there an intervening definition of r.to between
   250  	// the block defining 'from' and some reference to it?
   251  	forEachLexicalRef(r.pkg, from, func(id *ast.Ident, block *types.Scope) bool {
   252  		// Find the block that defines the found reference.
   253  		// It may be an ancestor.
   254  		fromBlock, _ := block.LookupParent(from.Name(), id.Pos())
   255  		// See what r.to would resolve to in the same scope.
   256  		toBlock, to := block.LookupParent(r.to, id.Pos())
   257  		if to != nil {
   258  			// sub-block conflict
   259  			if deeper(toBlock, fromBlock) {
   260  				r.errorf(from.Pos(), "renaming this %s %q to %q",
   261  					objectKind(from), from.Name(), r.to)
   262  				r.errorf(id.Pos(), "\twould cause this reference to become shadowed")
   263  				r.errorf(to.Pos(), "\tby this intervening %s definition",
   264  					objectKind(to))
   265  				return false // stop
   266  			}
   267  		}
   268  		return true
   269  	})
   270  
   271  	// Renaming a type that is used as an embedded field
   272  	// requires renaming the field too. e.g.
   273  	// 	type T int // if we rename this to U..
   274  	// 	var s struct {T}
   275  	// 	print(s.T) // ...this must change too
   276  	if _, ok := from.(*types.TypeName); ok {
   277  		for id, obj := range r.pkg.GetTypesInfo().Uses {
   278  			if obj == from {
   279  				if field := r.pkg.GetTypesInfo().Defs[id]; field != nil {
   280  					r.check(field)
   281  				}
   282  			}
   283  		}
   284  	}
   285  }
   286  
   287  // deeper reports whether block x is lexically deeper than y.
   288  func deeper(x, y *types.Scope) bool {
   289  	if x == y || x == nil {
   290  		return false
   291  	} else if y == nil {
   292  		return true
   293  	} else {
   294  		return deeper(x.Parent(), y.Parent())
   295  	}
   296  }
   297  
   298  // Scope and Position
   299  //
   300  // Consider a function f declared as:
   301  //
   302  //	func f[T *U, U *T](p, q T) (r, s U) { var ( v T; w = v ); type (t *t; u t) }
   303  //	^                                  ^           ^      ^         ^     ^
   304  ///   {T,U}                           {p,q,r,s}        v      w         t     u
   305  //
   306  // All objects {T, U, p, q, r, s, local} belong to the same lexical
   307  // block, the function scope, which is found in types.Info.Scopes
   308  // for f's FuncType. (A function body's BlockStmt does not have
   309  // an associated scope; only nested BlockStmts do.)
   310  //
   311  // The effective scope of each object is different:
   312  //
   313  //   - The type parameters T and U, whose constraints may refer to each
   314  //     other, all have a scope that starts at the beginning of the
   315  //     FuncDecl.Type.Func token.
   316  //
   317  //   - The parameter and result variables {p,q,r,s} can reference the
   318  //     type parameters but not each other, so their scopes all start at
   319  //     the end of the FuncType.
   320  //     (Prior to go1.22 it was--incorrectly--unset; see #64295).
   321  //     Beware also that Scope.Innermost does not currently work correctly for
   322  //     type parameters: it returns the scope of the package, not the function.
   323  //
   324  //   - Each const or var {v,w} declared within the function body has a
   325  //     scope that begins at the end of its ValueSpec, or after the
   326  //     AssignStmt for a var declared by ":=".
   327  //
   328  //   - Each type {t,u} in the body has a scope that that begins at
   329  //     the start of the TypeSpec, so they can be self-recursive
   330  //     but--unlike package-level types--not mutually recursive.
   331  
   332  // forEachLexicalRef calls fn(id, block) for each identifier id in package
   333  // pkg that is a reference to obj in lexical scope.  block is the
   334  // lexical block enclosing the reference.  If fn returns false the
   335  // iteration is terminated and findLexicalRefs returns false.
   336  func forEachLexicalRef(pkg *cache.Package, obj types.Object, fn func(id *ast.Ident, block *types.Scope) bool) bool {
   337  	ok := true
   338  	var stack []ast.Node
   339  
   340  	var visit func(n ast.Node) bool
   341  	visit = func(n ast.Node) bool {
   342  		if n == nil {
   343  			stack = stack[:len(stack)-1] // pop
   344  			return false
   345  		}
   346  		if !ok {
   347  			return false // bail out
   348  		}
   349  
   350  		stack = append(stack, n) // push
   351  		switch n := n.(type) {
   352  		case *ast.Ident:
   353  			if pkg.GetTypesInfo().Uses[n] == obj {
   354  				block := enclosingBlock(pkg.GetTypesInfo(), stack)
   355  				if !fn(n, block) {
   356  					ok = false
   357  				}
   358  			}
   359  			return visit(nil) // pop stack
   360  
   361  		case *ast.SelectorExpr:
   362  			// don't visit n.Sel
   363  			ast.Inspect(n.X, visit)
   364  			return visit(nil) // pop stack, don't descend
   365  
   366  		case *ast.CompositeLit:
   367  			// Handle recursion ourselves for struct literals
   368  			// so we don't visit field identifiers.
   369  			tv, ok := pkg.GetTypesInfo().Types[n]
   370  			if !ok {
   371  				return visit(nil) // pop stack, don't descend
   372  			}
   373  			// TODO(adonovan): fix: for generics, should be T.core not T.underlying.
   374  			if _, ok := Deref(tv.Type).Underlying().(*types.Struct); ok {
   375  				if n.Type != nil {
   376  					ast.Inspect(n.Type, visit)
   377  				}
   378  				for _, elt := range n.Elts {
   379  					if kv, ok := elt.(*ast.KeyValueExpr); ok {
   380  						ast.Inspect(kv.Value, visit)
   381  					} else {
   382  						ast.Inspect(elt, visit)
   383  					}
   384  				}
   385  				return visit(nil) // pop stack, don't descend
   386  			}
   387  		}
   388  		return true
   389  	}
   390  
   391  	for _, f := range pkg.GetSyntax() {
   392  		ast.Inspect(f, visit)
   393  		if len(stack) != 0 {
   394  			panic(stack)
   395  		}
   396  		if !ok {
   397  			break
   398  		}
   399  	}
   400  	return ok
   401  }
   402  
   403  // enclosingBlock returns the innermost block logically enclosing the
   404  // specified AST node (an ast.Ident), specified in the form of a path
   405  // from the root of the file, [file...n].
   406  func enclosingBlock(info *types.Info, stack []ast.Node) *types.Scope {
   407  	for i := range stack {
   408  		n := stack[len(stack)-1-i]
   409  		// For some reason, go/types always associates a
   410  		// function's scope with its FuncType.
   411  		// See comments about scope above.
   412  		switch f := n.(type) {
   413  		case *ast.FuncDecl:
   414  			n = f.Type
   415  		case *ast.FuncLit:
   416  			n = f.Type
   417  		}
   418  		if b := info.Scopes[n]; b != nil {
   419  			return b
   420  		}
   421  	}
   422  	panic("no Scope for *ast.File")
   423  }
   424  
   425  func (r *renamer) checkLabel(label *types.Label) {
   426  	// Check there are no identical labels in the function's label block.
   427  	// (Label blocks don't nest, so this is easy.)
   428  	if prev := label.Parent().Lookup(r.to); prev != nil {
   429  		r.errorf(label.Pos(), "renaming this label %q to %q", label.Name(), prev.Name())
   430  		r.errorf(prev.Pos(), "\twould conflict with this one")
   431  	}
   432  }
   433  
   434  // checkStructField checks that the field renaming will not cause
   435  // conflicts at its declaration, or ambiguity or changes to any selection.
   436  func (r *renamer) checkStructField(from *types.Var) {
   437  
   438  	// If this is the declaring package, check that the struct
   439  	// declaration is free of field conflicts, and field/method
   440  	// conflicts.
   441  	//
   442  	// go/types offers no easy way to get from a field (or interface
   443  	// method) to its declaring struct (or interface), so we must
   444  	// ascend the AST.
   445  	if pgf, ok := enclosingFile(r.pkg, from.Pos()); ok {
   446  		path, _ := astutil.PathEnclosingInterval(pgf.File, from.Pos(), from.Pos())
   447  		// path matches this pattern:
   448  		// [Ident SelectorExpr? StarExpr? Field FieldList StructType ParenExpr* ... File]
   449  
   450  		// Ascend to FieldList.
   451  		var i int
   452  		for {
   453  			if _, ok := path[i].(*ast.FieldList); ok {
   454  				break
   455  			}
   456  			i++
   457  		}
   458  		i++
   459  		tStruct := path[i].(*ast.StructType)
   460  		i++
   461  		// Ascend past parens (unlikely).
   462  		for {
   463  			_, ok := path[i].(*ast.ParenExpr)
   464  			if !ok {
   465  				break
   466  			}
   467  			i++
   468  		}
   469  		if spec, ok := path[i].(*ast.TypeSpec); ok {
   470  			// This struct is also a named type.
   471  			// We must check for direct (non-promoted) field/field
   472  			// and method/field conflicts.
   473  			named := r.pkg.GetTypesInfo().Defs[spec.Name].Type()
   474  			prev, indices, _ := types.LookupFieldOrMethod(named, true, r.pkg.GetTypes(), r.to)
   475  			if len(indices) == 1 {
   476  				r.errorf(from.Pos(), "renaming this field %q to %q",
   477  					from.Name(), r.to)
   478  				r.errorf(prev.Pos(), "\twould conflict with this %s",
   479  					objectKind(prev))
   480  				return // skip checkSelections to avoid redundant errors
   481  			}
   482  		} else {
   483  			// This struct is not a named type.
   484  			// We need only check for direct (non-promoted) field/field conflicts.
   485  			T := r.pkg.GetTypesInfo().Types[tStruct].Type.Underlying().(*types.Struct)
   486  			for i := 0; i < T.NumFields(); i++ {
   487  				if prev := T.Field(i); prev.Name() == r.to {
   488  					r.errorf(from.Pos(), "renaming this field %q to %q",
   489  						from.Name(), r.to)
   490  					r.errorf(prev.Pos(), "\twould conflict with this field")
   491  					return // skip checkSelections to avoid redundant errors
   492  				}
   493  			}
   494  		}
   495  	}
   496  
   497  	// Renaming an anonymous field requires renaming the type too. e.g.
   498  	// 	print(s.T)       // if we rename T to U,
   499  	// 	type T int       // this and
   500  	// 	var s struct {T} // this must change too.
   501  	if from.Anonymous() {
   502  		if named, ok := from.Type().(*types.Named); ok {
   503  			r.check(named.Obj())
   504  		} else if named, ok := Deref(from.Type()).(*types.Named); ok {
   505  			r.check(named.Obj())
   506  		}
   507  	}
   508  
   509  	// Check integrity of existing (field and method) selections.
   510  	r.checkSelections(from)
   511  }
   512  
   513  // checkSelections checks that all uses and selections that resolve to
   514  // the specified object would continue to do so after the renaming.
   515  func (r *renamer) checkSelections(from types.Object) {
   516  	pkg := r.pkg
   517  	typ := pkg.GetTypes()
   518  	{
   519  		if id := someUse(pkg.GetTypesInfo(), from); id != nil {
   520  			if !r.checkExport(id, typ, from) {
   521  				return
   522  			}
   523  		}
   524  
   525  		for syntax, sel := range pkg.GetTypesInfo().Selections {
   526  			// There may be extant selections of only the old
   527  			// name or only the new name, so we must check both.
   528  			// (If neither, the renaming is sound.)
   529  			//
   530  			// In both cases, we wish to compare the lengths
   531  			// of the implicit field path (Selection.Index)
   532  			// to see if the renaming would change it.
   533  			//
   534  			// If a selection that resolves to 'from', when renamed,
   535  			// would yield a path of the same or shorter length,
   536  			// this indicates ambiguity or a changed referent,
   537  			// analogous to same- or sub-block lexical conflict.
   538  			//
   539  			// If a selection using the name 'to' would
   540  			// yield a path of the same or shorter length,
   541  			// this indicates ambiguity or shadowing,
   542  			// analogous to same- or super-block lexical conflict.
   543  
   544  			// TODO(adonovan): fix: derive from Types[syntax.X].Mode
   545  			// TODO(adonovan): test with pointer, value, addressable value.
   546  			isAddressable := true
   547  
   548  			if sel.Obj() == from {
   549  				if obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), r.to); obj != nil {
   550  					// Renaming this existing selection of
   551  					// 'from' may block access to an existing
   552  					// type member named 'to'.
   553  					delta := len(indices) - len(sel.Index())
   554  					if delta > 0 {
   555  						continue // no ambiguity
   556  					}
   557  					r.selectionConflict(from, delta, syntax, obj)
   558  					return
   559  				}
   560  			} else if sel.Obj().Name() == r.to {
   561  				if obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), from.Name()); obj == from {
   562  					// Renaming 'from' may cause this existing
   563  					// selection of the name 'to' to change
   564  					// its meaning.
   565  					delta := len(indices) - len(sel.Index())
   566  					if delta > 0 {
   567  						continue //  no ambiguity
   568  					}
   569  					r.selectionConflict(from, -delta, syntax, sel.Obj())
   570  					return
   571  				}
   572  			}
   573  		}
   574  	}
   575  }
   576  
   577  func (r *renamer) selectionConflict(from types.Object, delta int, syntax *ast.SelectorExpr, obj types.Object) {
   578  	r.errorf(from.Pos(), "renaming this %s %q to %q",
   579  		objectKind(from), from.Name(), r.to)
   580  
   581  	switch {
   582  	case delta < 0:
   583  		// analogous to sub-block conflict
   584  		r.errorf(syntax.Sel.Pos(),
   585  			"\twould change the referent of this selection")
   586  		r.errorf(obj.Pos(), "\tof this %s", objectKind(obj))
   587  	case delta == 0:
   588  		// analogous to same-block conflict
   589  		r.errorf(syntax.Sel.Pos(),
   590  			"\twould make this reference ambiguous")
   591  		r.errorf(obj.Pos(), "\twith this %s", objectKind(obj))
   592  	case delta > 0:
   593  		// analogous to super-block conflict
   594  		r.errorf(syntax.Sel.Pos(),
   595  			"\twould shadow this selection")
   596  		r.errorf(obj.Pos(), "\tof the %s declared here",
   597  			objectKind(obj))
   598  	}
   599  }
   600  
   601  // checkMethod performs safety checks for renaming a method.
   602  // There are three hazards:
   603  // - declaration conflicts
   604  // - selection ambiguity/changes
   605  // - entailed renamings of assignable concrete/interface types.
   606  //
   607  // We reject renamings initiated at concrete methods if it would
   608  // change the assignability relation.  For renamings of abstract
   609  // methods, we rename all methods transitively coupled to it via
   610  // assignability.
   611  func (r *renamer) checkMethod(from *types.Func) {
   612  	// e.g. error.Error
   613  	if from.Pkg() == nil {
   614  		r.errorf(from.Pos(), "you cannot rename built-in method %s", from)
   615  		return
   616  	}
   617  
   618  	// ASSIGNABILITY: We reject renamings of concrete methods that
   619  	// would break a 'satisfy' constraint; but renamings of abstract
   620  	// methods are allowed to proceed, and we rename affected
   621  	// concrete and abstract methods as necessary.  It is the
   622  	// initial method that determines the policy.
   623  
   624  	// Check for conflict at point of declaration.
   625  	// Check to ensure preservation of assignability requirements.
   626  	R := recv(from).Type()
   627  	if types.IsInterface(R) {
   628  		// Abstract method
   629  
   630  		// declaration
   631  		prev, _, _ := types.LookupFieldOrMethod(R, false, from.Pkg(), r.to)
   632  		if prev != nil {
   633  			r.errorf(from.Pos(), "renaming this interface method %q to %q",
   634  				from.Name(), r.to)
   635  			r.errorf(prev.Pos(), "\twould conflict with this method")
   636  			return
   637  		}
   638  
   639  		// Check all interfaces that embed this one for
   640  		// declaration conflicts too.
   641  		{
   642  			// Start with named interface types (better errors)
   643  			for _, obj := range r.pkg.GetTypesInfo().Defs {
   644  				if obj, ok := obj.(*types.TypeName); ok && types.IsInterface(obj.Type()) {
   645  					f, _, _ := types.LookupFieldOrMethod(
   646  						obj.Type(), false, from.Pkg(), from.Name())
   647  					if f == nil {
   648  						continue
   649  					}
   650  					t, _, _ := types.LookupFieldOrMethod(
   651  						obj.Type(), false, from.Pkg(), r.to)
   652  					if t == nil {
   653  						continue
   654  					}
   655  					r.errorf(from.Pos(), "renaming this interface method %q to %q",
   656  						from.Name(), r.to)
   657  					r.errorf(t.Pos(), "\twould conflict with this method")
   658  					r.errorf(obj.Pos(), "\tin named interface type %q", obj.Name())
   659  				}
   660  			}
   661  
   662  			// Now look at all literal interface types (includes named ones again).
   663  			for e, tv := range r.pkg.GetTypesInfo().Types {
   664  				if e, ok := e.(*ast.InterfaceType); ok {
   665  					_ = e
   666  					_ = tv.Type.(*types.Interface)
   667  					// TODO(adonovan): implement same check as above.
   668  				}
   669  			}
   670  		}
   671  
   672  		// assignability
   673  		//
   674  		// Find the set of concrete or abstract methods directly
   675  		// coupled to abstract method 'from' by some
   676  		// satisfy.Constraint, and rename them too.
   677  		for key := range r.satisfy() {
   678  			// key = (lhs, rhs) where lhs is always an interface.
   679  
   680  			lsel := r.msets.MethodSet(key.LHS).Lookup(from.Pkg(), from.Name())
   681  			if lsel == nil {
   682  				continue
   683  			}
   684  			rmethods := r.msets.MethodSet(key.RHS)
   685  			rsel := rmethods.Lookup(from.Pkg(), from.Name())
   686  			if rsel == nil {
   687  				continue
   688  			}
   689  
   690  			// If both sides have a method of this name,
   691  			// and one of them is m, the other must be coupled.
   692  			var coupled *types.Func
   693  			switch from {
   694  			case lsel.Obj():
   695  				coupled = rsel.Obj().(*types.Func)
   696  			case rsel.Obj():
   697  				coupled = lsel.Obj().(*types.Func)
   698  			default:
   699  				continue
   700  			}
   701  
   702  			// We must treat concrete-to-interface
   703  			// constraints like an implicit selection C.f of
   704  			// each interface method I.f, and check that the
   705  			// renaming leaves the selection unchanged and
   706  			// unambiguous.
   707  			//
   708  			// Fun fact: the implicit selection of C.f
   709  			// 	type I interface{f()}
   710  			// 	type C struct{I}
   711  			// 	func (C) g()
   712  			//      var _ I = C{} // here
   713  			// yields abstract method I.f.  This can make error
   714  			// messages less than obvious.
   715  			//
   716  			if !types.IsInterface(key.RHS) {
   717  				// The logic below was derived from checkSelections.
   718  
   719  				rtosel := rmethods.Lookup(from.Pkg(), r.to)
   720  				if rtosel != nil {
   721  					rto := rtosel.Obj().(*types.Func)
   722  					delta := len(rsel.Index()) - len(rtosel.Index())
   723  					if delta < 0 {
   724  						continue // no ambiguity
   725  					}
   726  
   727  					// TODO(adonovan): record the constraint's position.
   728  					keyPos := token.NoPos
   729  
   730  					r.errorf(from.Pos(), "renaming this method %q to %q",
   731  						from.Name(), r.to)
   732  					if delta == 0 {
   733  						// analogous to same-block conflict
   734  						r.errorf(keyPos, "\twould make the %s method of %s invoked via interface %s ambiguous",
   735  							r.to, key.RHS, key.LHS)
   736  						r.errorf(rto.Pos(), "\twith (%s).%s",
   737  							recv(rto).Type(), r.to)
   738  					} else {
   739  						// analogous to super-block conflict
   740  						r.errorf(keyPos, "\twould change the %s method of %s invoked via interface %s",
   741  							r.to, key.RHS, key.LHS)
   742  						r.errorf(coupled.Pos(), "\tfrom (%s).%s",
   743  							recv(coupled).Type(), r.to)
   744  						r.errorf(rto.Pos(), "\tto (%s).%s",
   745  							recv(rto).Type(), r.to)
   746  					}
   747  					return // one error is enough
   748  				}
   749  			}
   750  
   751  			if !r.changeMethods {
   752  				// This should be unreachable.
   753  				r.errorf(from.Pos(), "internal error: during renaming of abstract method %s", from)
   754  				r.errorf(coupled.Pos(), "\tchangedMethods=false, coupled method=%s", coupled)
   755  				r.errorf(from.Pos(), "\tPlease file a bug report")
   756  				return
   757  			}
   758  
   759  			// Rename the coupled method to preserve assignability.
   760  			r.check(coupled)
   761  		}
   762  	} else {
   763  		// Concrete method
   764  
   765  		// declaration
   766  		prev, indices, _ := types.LookupFieldOrMethod(R, true, from.Pkg(), r.to)
   767  		if prev != nil && len(indices) == 1 {
   768  			r.errorf(from.Pos(), "renaming this method %q to %q",
   769  				from.Name(), r.to)
   770  			r.errorf(prev.Pos(), "\twould conflict with this %s",
   771  				objectKind(prev))
   772  			return
   773  		}
   774  
   775  		// assignability
   776  		//
   777  		// Find the set of abstract methods coupled to concrete
   778  		// method 'from' by some satisfy.Constraint, and rename
   779  		// them too.
   780  		//
   781  		// Coupling may be indirect, e.g. I.f <-> C.f via type D.
   782  		//
   783  		// 	type I interface {f()}
   784  		//	type C int
   785  		//	type (C) f()
   786  		//	type D struct{C}
   787  		//	var _ I = D{}
   788  		//
   789  		for key := range r.satisfy() {
   790  			// key = (lhs, rhs) where lhs is always an interface.
   791  			if types.IsInterface(key.RHS) {
   792  				continue
   793  			}
   794  			rsel := r.msets.MethodSet(key.RHS).Lookup(from.Pkg(), from.Name())
   795  			if rsel == nil || rsel.Obj() != from {
   796  				continue // rhs does not have the method
   797  			}
   798  			lsel := r.msets.MethodSet(key.LHS).Lookup(from.Pkg(), from.Name())
   799  			if lsel == nil {
   800  				continue
   801  			}
   802  			imeth := lsel.Obj().(*types.Func)
   803  
   804  			// imeth is the abstract method (e.g. I.f)
   805  			// and key.RHS is the concrete coupling type (e.g. D).
   806  			if !r.changeMethods {
   807  				r.errorf(from.Pos(), "renaming this method %q to %q",
   808  					from.Name(), r.to)
   809  				var pos token.Pos
   810  				var iface string
   811  
   812  				I := recv(imeth).Type()
   813  				if named, ok := I.(*types.Named); ok {
   814  					pos = named.Obj().Pos()
   815  					iface = "interface " + named.Obj().Name()
   816  				} else {
   817  					pos = from.Pos()
   818  					iface = I.String()
   819  				}
   820  				r.errorf(pos, "\twould make %s no longer assignable to %s",
   821  					key.RHS, iface)
   822  				r.errorf(imeth.Pos(), "\t(rename %s.%s if you intend to change both types)",
   823  					I, from.Name())
   824  				return // one error is enough
   825  			}
   826  
   827  			// Rename the coupled interface method to preserve assignability.
   828  			r.check(imeth)
   829  		}
   830  	}
   831  
   832  	// Check integrity of existing (field and method) selections.
   833  	// We skip this if there were errors above, to avoid redundant errors.
   834  	r.checkSelections(from)
   835  }
   836  
   837  func (r *renamer) checkExport(id *ast.Ident, pkg *types.Package, from types.Object) bool {
   838  	// Reject cross-package references if r.to is unexported.
   839  	// (Such references may be qualified identifiers or field/method
   840  	// selections.)
   841  	if !ast.IsExported(r.to) && pkg != from.Pkg() {
   842  		r.errorf(from.Pos(),
   843  			"renaming %q to %q would make it unexported",
   844  			from.Name(), r.to)
   845  		r.errorf(id.Pos(), "\tbreaking references from packages such as %q",
   846  			pkg.Path())
   847  		return false
   848  	}
   849  	return true
   850  }
   851  
   852  // satisfy returns the set of interface satisfaction constraints.
   853  func (r *renamer) satisfy() map[satisfy.Constraint]bool {
   854  	if r.satisfyConstraints == nil {
   855  		// Compute on demand: it's expensive.
   856  		var f satisfy.Finder
   857  		pkg := r.pkg
   858  		{
   859  			// From satisfy.Finder documentation:
   860  			//
   861  			// The package must be free of type errors, and
   862  			// info.{Defs,Uses,Selections,Types} must have been populated by the
   863  			// type-checker.
   864  			//
   865  			// Only proceed if all packages have no errors.
   866  			if len(pkg.GetParseErrors()) > 0 || len(pkg.GetTypeErrors()) > 0 {
   867  				r.errorf(token.NoPos, // we don't have a position for this error.
   868  					"renaming %q to %q not possible because %q has errors",
   869  					r.from, r.to, pkg.Metadata().PkgPath)
   870  				return nil
   871  			}
   872  			f.Find(pkg.GetTypesInfo(), pkg.GetSyntax())
   873  		}
   874  		r.satisfyConstraints = f.Result
   875  	}
   876  	return r.satisfyConstraints
   877  }
   878  
   879  // -- helpers ----------------------------------------------------------
   880  
   881  // recv returns the method's receiver.
   882  func recv(meth *types.Func) *types.Var {
   883  	return meth.Type().(*types.Signature).Recv()
   884  }
   885  
   886  // someUse returns an arbitrary use of obj within info.
   887  func someUse(info *types.Info, obj types.Object) *ast.Ident {
   888  	for id, o := range info.Uses {
   889  		if o == obj {
   890  			return id
   891  		}
   892  	}
   893  	return nil
   894  }
   895  
   896  func objectKind(obj types.Object) string {
   897  	if obj == nil {
   898  		return "nil object"
   899  	}
   900  	switch obj := obj.(type) {
   901  	case *types.PkgName:
   902  		return "imported package name"
   903  	case *types.TypeName:
   904  		return "type"
   905  	case *types.Var:
   906  		if obj.IsField() {
   907  			return "field"
   908  		}
   909  	case *types.Func:
   910  		if obj.Type().(*types.Signature).Recv() != nil {
   911  			return "method"
   912  		}
   913  	}
   914  	// label, func, var, const
   915  	return strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types."))
   916  }
   917  
   918  // NB: for renamings, blank is not considered valid.
   919  func isValidIdentifier(id string) bool {
   920  	if id == "" || id == "_" {
   921  		return false
   922  	}
   923  	for i, r := range id {
   924  		if !isLetter(r) && (i == 0 || !isDigit(r)) {
   925  			return false
   926  		}
   927  	}
   928  	return token.Lookup(id) == token.IDENT
   929  }
   930  
   931  // isLocal reports whether obj is local to some function.
   932  // Precondition: not a struct field or interface method.
   933  func isLocal(obj types.Object) bool {
   934  	// [... 5=stmt 4=func 3=file 2=pkg 1=universe]
   935  	var depth int
   936  	for scope := obj.Parent(); scope != nil; scope = scope.Parent() {
   937  		depth++
   938  	}
   939  	return depth >= 4
   940  }
   941  
   942  func isPackageLevel(obj types.Object) bool {
   943  	if obj == nil {
   944  		return false
   945  	}
   946  	return obj.Pkg().Scope().Lookup(obj.Name()) == obj
   947  }
   948  
   949  // -- Plundered from go/scanner: ---------------------------------------
   950  
   951  func isLetter(ch rune) bool {
   952  	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
   953  }
   954  
   955  func isDigit(ch rune) bool {
   956  	return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
   957  }