Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plugin: fails to correctly reference type from vendor #27062

Open
BryceDFisher opened this issue Aug 17, 2018 · 3 comments
Open

plugin: fails to correctly reference type from vendor #27062

BryceDFisher opened this issue Aug 17, 2018 · 3 comments

Comments

@BryceDFisher
Copy link

@BryceDFisher BryceDFisher commented Aug 17, 2018

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.10.3 linux/amd64

Does this issue reproduce with the latest release?

yes, 1.10.3

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN="/home/fisherb/go/bin"
GOCACHE="/home/fisherb/.cache/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/fisherb/go"
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build861164804=/tmp/go-build -gno-record-gcc-switches"

What did you do?

When using plugins, in a typical github vendoring approach: $GOPATH/src/github.com/author/repo/package with resources in $GOPATH/src/github.com/author/repo/package/vendor/github.com/author/repoa/package, if the plugin was compiled using a separate package, that is ultimately imported into the main package via vendoring, the types don't match and casting is not possible.

This tree works (rooted at $GOPATH/src/github.com:

plbody
└── pltypes
    ├── plbody
    │   └── plbody.go
    └── pltypes.go
plmain
└── plmain.go
plplugin
└── plplugin
    └── plplugin.go

This tree does not work (rooted at $GOPATH/src/github.com)

plbody
└── pltypes
    ├── plbody
    │   └── plbody.go
    └── pltypes.go
plmain
├── plmain.go
└── vendor
    └── github.com
        └── plbody
            └── pltypes
                ├── plbody
                │   └── plbody.go
                └── pltypes.go
plplugin
└── plplugin
    ├── plplugin.go
    └── vendor
        └── github.com
            └── plbody
                └── pltypes
                    ├── plbody
                    │   └── plbody.go
                    └── pltypes.go

In both the working and not working cases, the imports are the same, just the directory structure is different.
plbody.go:

package plbody

import (
        "log"
        "plugin"

        "github.com/plbody/pltypes"
)

//Test is the test function
var Test func(a pltypes.A, s string) error

func init() {
        pl, err := plugin.Open("plplugin.so")
        if err != nil {
                log.Fatalf("Unable to find plugin: %s", err.Error())
        }
        obj, err := pl.Lookup("Test")
        if err != nil {
                log.Fatalf("Unable to find Test in plugin: %s", err.Error())
        }

        t := obj.(pltypes.Tester)
        Test = t.Test
}

pltypes.go:

package pltypes

//Tester contains a test function
type Tester interface {
        Test(A, string) error
}

//A A is a custom data type
type A struct {
        Data string
}

plmain.go:

package main

import (
        "log"

        "github.com/plbody/pltypes"
        "github.com/plbody/pltypes/plbody"
)

func main() {
        log.Printf("%v", plbody.Test(pltypes.A{}, ""))
}

plplugin.go:

package main

import "github.com/plbody/pltypes"

type test struct{}

//Test is the exported test struct
var Test test

func main() {}

func (t test) Test(a pltypes.A, s string) error {
        return nil
}

What did you expect to see?

2018/08/17 15:03:34 <nil>

What did you see instead?

The types are not castable to each other:

panic: interface conversion: *main.test is not pltypes.Tester: missing method Test

goroutine 1 [running]:
github.com/plmain/vendor/github.com/plbody/pltypes/plbody.init.0()
        /home/fisherb/go/src/github.com/plmain/vendor/github.com/plbody/pltypes/plbody/plbody.go:23 +0xcf
@andybons

This comment has been minimized.

Copy link
Member

@andybons andybons commented Aug 17, 2018

@andybons andybons changed the title Plugin fails to correctly reference type from vendor plugin: fails to correctly reference type from vendor Aug 17, 2018
@andybons andybons added this to the Unplanned milestone Aug 17, 2018
@BryceDFisher

This comment has been minimized.

Copy link
Author

@BryceDFisher BryceDFisher commented Aug 21, 2018

Upon further inspection, it appears the reflection does not view the type A as the same type in the function definition, despite the fact that reflect.TypeOf(A) returns the same PkgPath ("") and Name ("A"). If you remove A from the function definition, everything works as expected.

@BryceDFisher

This comment has been minimized.

Copy link
Author

@BryceDFisher BryceDFisher commented Aug 28, 2018

It looks like the discussion from https://github.com/golang/proposal/blob/master/design/25719-go15vendor.md and the comment in

// By default, Import searches vendor directories
ensure that plugins built with vendor directories will never see types as used above as the same type at run time.

Does anyone have a better method that I could use in my example to load the plugin with the custom type pltypes.A? Or should I assume that plugins will not support this behavior for the foreseeable future and therefore I should move on to other options.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.