How does Go solve name clashes when doing dot imports?

546 views
Skip to first unread message

Dmitri Shuralyov

unread,
Jul 15, 2014, 4:47:54 AM7/15/14
to golan...@googlegroups.com
From Go's spec on scopes,

Go is lexically scoped using blocks:

  1. The scope of a predeclared identifier is the universe block.
  2. The scope of an identifier denoting a constant, type, variable, or function (but not method) declared at top level (outside any function) is the package block.
  3. The scope of the package name of an imported package is the file block of the file containing the import declaration.
  4. The scope of an identifier denoting a method receiver, function parameter, or result variable is the function body.
  5. The scope of a constant or variable identifier declared inside a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl for short variable declarations) and ends at the end of the innermost containing block.
  6. The scope of a type identifier declared inside a function begins at the identifier in the TypeSpec and ends at the end of the innermost containing block.
If an explicit period (.) appears instead of a name, all the package's exported identifiers declared in that package's package block will be declared in the importing source file's file block and must be accessed without a qualifier.

Doing a dot import is only legal when none of its exported identifiers overlap with the package's existing exported identifiers (it can't be legal because there'd be no way to distinguish two identifiers with identical names).

./main.go:11: Foo redeclared in this block
previous declaration during import "some/import/path"

However, that doesn't apply for unexported identifers, since they're not accessible anyway, it's okay for a package being dot-imported to have the same unexported identifer as the main package.

But what happens if an exported func within the package being dot-imported refers to one of its unexported identifiers, but that name is already used in the package block of the main package...

Say, we import Foo() which calls foo(), but we already have a foo() in main package.

Does anyone know how Go handles such scenarios?

---

I want to learn the answer for 2 reasons:

1. To know more about how Go works.
2. I have some Go code that takes an Go package (via import path string) and rewrites it as a single Go AST with all files merged and all dot imports inlined. It works great when no unexported names overlap, but fails when they do.

Thanks!

Ian Lance Taylor

unread,
Jul 15, 2014, 9:10:56 AM7/15/14
to Dmitri Shuralyov, golang-nuts
On Tue, Jul 15, 2014 at 1:47 AM, Dmitri Shuralyov <shur...@gmail.com> wrote:
>
> But what happens if an exported func within the package being dot-imported
> refers to one of its unexported identifiers, but that name is already used
> in the package block of the main package...
>
> Say, we import Foo() which calls foo(), but we already have a foo() in main
> package.

It will call the foo in the dot-imported package, not the foo in the
main package.


> 1. To know more about how Go works.
> 2. I have some Go code that takes an Go package (via import path string) and
> rewrites it as a single Go AST with all files merged and all dot imports
> inlined. It works great when no unexported names overlap, but fails when
> they do.

You have to not merge identifiers with the same unexported name that
come from different packages. If you are generating Go code, you have
to arrange for unexported names to be mangled in some way.

Ian
Reply all
Reply to author
Forward
0 new messages