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

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