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

cmd/go: allow cross-module internal imports based on import path prefix #23970

Closed
nathankerr opened this issue Feb 21, 2018 · 16 comments
Closed
Labels
FrozenDueToAge modules NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Milestone

Comments

@nathankerr
Copy link

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

go version go1.10 darwin/amd64

Does this issue reproduce with the latest release?

go version go1.10 darwin/amd64 vgo:2018-02-20.1

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

GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/alaster/Library/Caches/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/alaster"
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
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 -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/qj/7sh5tjq9291gb64gb0f50p0w0000gn/T/go-build886364026=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

In a new directory with the following files

main.go:

package main

import "github.com/gonum/stat"

func main() {
	println(stat.StdDev([]float64{1.0, 2.0}, nil))
}

go.mod:

module "stat"

vgo build fails to build this package.

What did you expect to see?

vgo build should have produced an executable like go build does

What did you see instead?

$ vgo build
vgo: resolving import "github.com/gonum/stat"
vgo: finding github.com/gonum/stat (latest)
vgo: adding github.com/gonum/stat v0.0.0-20180125090729-ec9c8a1062f4
vgo: resolving import "github.com/gonum/floats"
vgo: finding github.com/gonum/floats (latest)
vgo: adding github.com/gonum/floats v0.0.0-20180125090339-7de1f4ea7ab5
vgo: resolving import "github.com/gonum/matrix"
vgo: finding github.com/gonum/matrix (latest)
vgo: adding github.com/gonum/matrix v0.0.0-20180124231301-a41cc49d4c29
vgo: resolving import "github.com/gonum/internal/asm/f64"
vgo: finding github.com/gonum/internal (latest)
vgo: adding github.com/gonum/internal v0.0.0-20180125090855-fda53f8d2571
vgo: resolving import "github.com/gonum/lapack"
vgo: finding github.com/gonum/lapack (latest)
vgo: adding github.com/gonum/lapack v0.0.0-20180125091020-f0b8b25edece
vgo: resolving import "github.com/gonum/blas"
vgo: finding github.com/gonum/blas (latest)
vgo: adding github.com/gonum/blas v0.0.0-20180125090452-e7c5890b24cf
../v/github.com/gonum/blas@v0.0.0-20180125090452-e7c5890b24cf/native/level1single.go:13:2: use of internal package not allowed
../v/github.com/gonum/floats@v0.0.0-20180125090339-7de1f4ea7ab5/floats.go:18:2: use of internal package not allowed

Additional Comments

The import "github.com/gonum/stat" has moved to "gonum.org/v1/gonum/stat" after which change the example builds as expected.

I'm reporting this because it highlights a difference in how go and vgo handle internal packages, in this case where the internal package is a separate repository.

@rsc
Copy link
Contributor

rsc commented Apr 2, 2018

The problem here is that github.com/gonum/blas imports github.com/gonum/internal/asm/f32, which is outside the blas module. We will need to decide what the rules are for cross-module internal like that.

@rsc rsc changed the title x/vgo: build with internal package that is also separate repository fails x/vgo: decide rules for cross-module internal imports Apr 2, 2018
@rsc rsc added the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Apr 2, 2018
@nathankerr
Copy link
Author

The internal packages design document states the rule as:

An import of a path containing the element “internal” is disallowed if the importing code is outside the tree rooted at the parent of the “internal” directory.

A compatible rule, thinking just in terms of import paths is:

An import of a path containing the element “internal” is disallowed if the importing code does not have the same path prefix as the “internal” path.

The example in this issue has github.com/gonum/blas importing github.com/gonum/internal/asm/f32. The path prefix for the internal import is "github.com/gonum". Since github.com/gonum/blas also has that prefix, the import would be allowed.

This modified rule would, however, allow a situation that is not allowed by the current implementation (go1.10.1): cross-GOPATH internal imports:

Given GOPATH=$HOME/a:$HOME/b and two files:

$HOME/a/src/prefix/importer/importer.go:

package importer

import "prefix/internal"

func G() {
	internal.F()
}

and $HOME/b/src/prefix/internal/internal.go:

package internal

func F() {
	println("internal")
}

The build fails with:

$ go build prefix/importer
a/src/prefix/importer/importer.go:3:8: use of internal package not allowed

The modified rule would not disallow this as it only considers the import path and not where the package is on disk.

When both files are in the same GOPATH root (e.g., GOPATH=$HOME/combined with files named combined/src/prefix/importer/importer.go and combined/src/prefix/internal/internal.go) the build succeeds.

This is the only case I know of where the modified rule differs from the current implementation.

The modified rule is, I believe, a valid interpretation of the current rule; thinking of the (de facto) import path hierarchy instead of the disk hierarchy.

@rsc
Copy link
Contributor

rsc commented Apr 3, 2018

@nathankerr, right, your counter-example is exactly why we can't redefine the general internal import rule as you described. That would allow, for example, every package in the world to import "internal/testenv", which is meant to be internal to the standard library. The use of directory, not import path, was intentional.

That said, it does seem like focusing on import path for the narrower case of "one module referring to packages in another module" does make sense, because those could have been in a single GOPATH before anyway.

I'll mark this NeedsFix but we need to be careful with the fix not to open things too far.

@rsc rsc changed the title x/vgo: decide rules for cross-module internal imports x/vgo: allow cross-module internal imports based on import path prefi Apr 3, 2018
@rsc rsc changed the title x/vgo: allow cross-module internal imports based on import path prefi x/vgo: allow cross-module internal imports based on import path prefix Apr 3, 2018
@rsc rsc added the NeedsFix The path to resolution is known, but the work has not been done. label Apr 3, 2018
@gopherbot gopherbot removed the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Apr 3, 2018
@nathankerr
Copy link
Author

@rsc I hadn't considered GOROOT. Good catch.

Viewing all modules as being in the same tree (separate from GOROOT) as if they were all in a single GOPATH keeps the original rule intact.

@tgulacsi
Copy link
Contributor

tgulacsi commented Apr 4, 2018

github.com/cznic/lldb imports github.com/cznic/internal/buffer which seems to be fordbidden, now.
What is the solution?

@cznic
Copy link
Contributor

cznic commented Apr 4, 2018

What is the solution?

@tgulacsi Regardless of the solution, if you meanwhile need any of those internal packages made generally importable, please fill an issue at cznic/internal and I will let it happen. The original intent was to let practice show/prove if those API are acceptable/working well. IIRC, they were not changed for a long time, if at all. So I guess it's safe to move them out from 'internal'.

@tgulacsi
Copy link
Contributor

tgulacsi commented Apr 4, 2018

Thanks, @cznic - my main concern is though I'd happily use vgo as it tries to solve some of my problems, I stumble walls everywhere - github.com/cznic/internal (for github.com/cznic/kv for camlistore.org/pkg/sorted/kvfile), github.com/russross/blackfriday (for I don't know what).

I'd file issues to those upstream packages, but I feel vgo is still in its infancy, and don't want to bother those nice guys for such a volatile target.

@rsc
Copy link
Contributor

rsc commented Apr 5, 2018

@tgulacsi I agree with you: we should be fixing vgo, not forcing other projects to work around its bugs.

@sbinet
Copy link
Member

sbinet commented Apr 10, 2018

another possible way to look at this: now that we have a go.mod file, we could perhaps add another (optional) section that lists modules that are allowed to import that module ?

that's what the internal special name was for in the end...

admittedly, this does complexify the logic.

@rsc rsc modified the milestones: vgo, Go1.11 Jul 12, 2018
@rsc rsc added the modules label Jul 12, 2018
@rsc rsc changed the title x/vgo: allow cross-module internal imports based on import path prefix cmd/go: allow cross-module internal imports based on import path prefix Jul 12, 2018
@bcmills bcmills self-assigned this Jul 13, 2018
@bcmills
Copy link
Contributor

bcmills commented Jul 13, 2018

@sbinet I don't think we have a use-case that requires an explicit list. Let's see how far we get with just the path-based approach for now.

@ChrisHines
Copy link
Contributor

I think this issue would also have an interesting interaction with the go mod -vendor and go build -getmode=vendor commands. Assuming go mod -vendor successfully copies the dependencies to the vendor folder that would restore the pre-module directory structure and presumably go build -getmode=vendor would work.

@gopherbot
Copy link

Change https://golang.org/cl/125676 mentions this issue: cmd/go: allow internal imports based on module paths

@bcmills
Copy link
Contributor

bcmills commented Jul 25, 2018

So, here's an interesting question: how should internal imports interact with replace directives?

Should the effective path for the replace directive be the import path seen by the program, or the module path as declared in the replacement's module definition? (The former is easier to implement, but the latter seems more correct.)

@gopherbot
Copy link

Change https://golang.org/cl/125836 mentions this issue: cmd/go: use replacement module path to check internal imports

gopherbot pushed a commit that referenced this issue Jul 31, 2018
Updates #23970.

Change-Id: I2e69ad15b9d1097bfeef9947f03cfa6834a6a049
Reviewed-on: https://go-review.googlesource.com/125676
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
jeet-parekh pushed a commit to jeet-parekh/go that referenced this issue Jul 31, 2018
Updates golang#23970.

Change-Id: I2e69ad15b9d1097bfeef9947f03cfa6834a6a049
Reviewed-on: https://go-review.googlesource.com/125676
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
jeet-parekh pushed a commit to jeet-parekh/go that referenced this issue Jul 31, 2018
Expand mod_internal tests to cover vendoring, replacements, and failure
messages.

Packages beginning with "golang_org/" resolve to $GOROOT/src/vendor, and should
therefore not be visible within module code.

Fixes golang#23970.

Change-Id: I706e9c4a1d1e025883e84b897972678d0fa3f2bd
Reviewed-on: https://go-review.googlesource.com/125836
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
@owenhaynes
Copy link

What was the outcome of this problem as hitting similar issues with github.com/mongodb/mongo-go-driver? And lets say trying to use github.com/mongodb/mongo-go-driver/core/connstring.

@bcmills
Copy link
Contributor

bcmills commented Sep 28, 2018

internal imports should work based on the import path. (The importer of an internal package must share the import-path prefix leading up to the /internal component, but can be in a separate module.)

@golang golang locked and limited conversation to collaborators Sep 28, 2019
@rsc rsc unassigned bcmills Jun 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge modules NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Projects
None yet
Development

No branches or pull requests

10 participants