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