Hi!

I am writing a special linting-like piece of code and struggle dealing with 
the Implements <https://golang.org/pkg/go/types/#Implements> that doesn't 
work for my configuration. I made a simplified testing example to show the 
issue:


   - I have package speaker with interface Speaker and its default 
   implementation.
   
   package speaker
   type Default struct{}
   func (Default) Speak(Arg) string {
      return "speak"
   }
   type Arg struct{}
   type Speaker interface {
      Speak(Arg) string
   }
   
   - 
   
   Now, I have another package, with "Russian speaker":
   
   
   package ru
   import "awesome/speaker"
   type Russian struct{}
   func (Russian) Speak(speaker.Arg) string {
      return "говорить"
   }
   
   - 
   
   An finally I have a main package
   
   
   package main
   
   import (
      "fmt"
      "go/ast"
      "go/importer"
      "go/parser"
      "go/token"
      "go/types"
      "path/filepath"
      "runtime"
   )
   
   func getPath() string {
      fpcs := make([]uintptr, 5)
      frameIter := runtime.CallersFrames(fpcs[:runtime.Callers(1, fpcs)])
      var frames []runtime.Frame
      frame, more := frameIter.Next()
      frames = append(frames, frame)
      if !more {
         panic("stack frames must exists for a call")
      }
      return filepath.Dir(frame.File)
   }
   
   func getTypes(path ...string) *types.Package {
      path = append([]string{getPath()}, path...)
      fullpath := filepath.Join(path...)
      fset := token.NewFileSet()
      pkgs, err := parser.ParseDir(fset, fullpath, nil, parser.ParseComments)
      if err != nil {
         panic(err)
      }
      for _, pkg := range pkgs {
         config := &types.Config{
            IgnoreFuncBodies: false,
            FakeImportC:      false,
            Error:            nil,
            Importer:         importer.Default(),
            Sizes:            nil,
            DisableUnusedImportCheck: false,
         }
         info := types.Info{
            Types: map[ast.Expr]types.TypeAndValue{},
            Defs:  map[*ast.Ident]types.Object{},
            Uses:  map[*ast.Ident]types.Object{},
         }
         var files []*ast.File
         for _, file := range pkg.Files {
            files = append(files, file)
         }
         typeInfo, err := config.Check(fullpath, fset, files, &info)
         if err != nil {
            panic(err)
         }
         return typeInfo
      }
      return nil
   }
   
   func main() {
      mainPkg := getTypes("speaker")
      ruPkg := getTypes("ru")
   
      iface := 
mainPkg.Scope().Lookup("Speaker").Type().Underlying().(*types.Interface)
      dflt := mainPkg.Scope().Lookup("Default").Type()
      russian := ruPkg.Scope().Lookup("Russian").Type()
   
      fmt.Println(types.Implements(dflt, iface))
      fmt.Println(types.Implements(russian, iface))
   }
   
   
Output is:
true
false

The output is true-true without the argument. Is it a feature or a bug? How 
can I walk around it?

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Attachment: package.tar.xz
Description: Binary data

Reply via email to