protoc-gen-go: fix generation of public imports (#549)

(*Generator).DefaultPackageName returns either a qualified ("pkg.name") or
unqualified ("name") name.

Prior to commit 9d4962b4, it based this decision on whether the
name was in the package we're generating code for.  After this
commit, it bases this on whether the name is in the file we're
currently generating code for. i.e., what was once an invariant
across all files is no longer.

This is mostly fine, except for one case: We run the generator
across files we do not generate code for, in order to build a list
of symbols used to generate code for public imports. This change
caused some of those symbols to no longer be qualified.

In particular, this causes bad generation for wrapper types of
publicly imported messages that contain a field whose type is
another message in the same publicly imported package.

Fix this. Clean up some effectively dead code in SetPackageNames
at the same time. Fix tests to catch this case. (It wouldn't have
caught it anyway, but imp.proto is supposed to contain a public import.
This seems to have been lost when exporting code to git. Fixed.)
diff --git a/Makefile b/Makefile
index 6a23868..63030d3 100644
--- a/Makefile
+++ b/Makefile
@@ -35,7 +35,7 @@
 	go install ./proto ./jsonpb ./ptypes ./protoc-gen-go
 
 test:
-	go test ./...
+	go test ./... ./protoc-gen-go/testdata
 
 clean:
 	go clean ./...
diff --git a/protoc-gen-go/generator/generator.go b/protoc-gen-go/generator/generator.go
index 6e1b72c..4edd311 100644
--- a/protoc-gen-go/generator/generator.go
+++ b/protoc-gen-go/generator/generator.go
@@ -95,6 +95,8 @@
 // A GoImportPath is the import path of a Go package. e.g., "google.golang.org/genproto/protobuf".
 type GoImportPath string
 
+func (p GoImportPath) String() string { return strconv.Quote(string(p)) }
+
 // A GoPackageName is the name of a Go package. e.g., "protobuf".
 type GoPackageName string
 
@@ -567,7 +569,7 @@
 
 	Pkg map[string]string // The names under which we import support packages
 
-	packageName      GoPackageName                  // What we're calling ourselves.
+	outputImportPath GoImportPath                   // Package we're generating code for.
 	allFiles         []*FileDescriptor              // All files in the tree
 	allFilesByName   map[string]*FileDescriptor     // All files by filename.
 	genFiles         []*FileDescriptor              // Those files we will generate output for.
@@ -677,7 +679,7 @@
 // Otherwise it returns the empty string.
 func (g *Generator) DefaultPackageName(obj Object) string {
 	importPath := obj.GoImportPath()
-	if importPath == g.file.importPath {
+	if importPath == g.outputImportPath {
 		return ""
 	}
 	return string(g.GoPackageName(importPath)) + "."
@@ -769,46 +771,20 @@
 // The package name must agree across all files being generated.
 // It also defines unique package names for all imported files.
 func (g *Generator) SetPackageNames() {
-	// Register the name for this package.  It will be the first name
-	// registered so is guaranteed to be unmodified.
-	pkg, explicit := g.genFiles[0].goPackageName()
+	g.outputImportPath = g.genFiles[0].importPath
 
-	// Check all files for an explicit go_package option.
-	for _, f := range g.genFiles {
-		thisPkg, thisExplicit := f.goPackageName()
-		if thisExplicit {
-			if !explicit {
-				// Let this file's go_package option serve for all input files.
-				pkg, explicit = thisPkg, true
-			} else if thisPkg != pkg {
-				g.Fail("inconsistent package names:", string(thisPkg), string(pkg))
-			}
+	// Check that all files have a consistent package name and import path.
+	pkg, _ := g.genFiles[0].goPackageName()
+	for _, f := range g.genFiles[1:] {
+		if a, b := g.genFiles[0].importPath, f.importPath; a != b {
+			g.Fail(fmt.Sprint("inconsistent package import paths: ", a, b))
+		}
+		thisPkg, _ := f.goPackageName()
+		if pkg != thisPkg {
+			g.Fail(fmt.Sprint("inconsistent package names: ", thisPkg, pkg))
 		}
 	}
 
-	// If we don't have an explicit go_package option but we have an
-	// import path, use that.
-	if !explicit {
-		p := g.defaultGoPackage()
-		if p != "" {
-			pkg, explicit = p, true
-		}
-	}
-
-	// If there was no go_package and no import path to use,
-	// double-check that all the inputs have the same implicit
-	// Go package name.
-	if !explicit {
-		for _, f := range g.genFiles {
-			thisPkg, _ := f.goPackageName()
-			if thisPkg != pkg {
-				g.Fail("inconsistent package names:", string(thisPkg), string(pkg))
-			}
-		}
-	}
-
-	g.packageName = pkg
-
 	// Names of support packages. These never vary (if there are conflicts,
 	// we rename the conflicting package), so this could be removed someday.
 	g.Pkg = map[string]string{
diff --git a/protoc-gen-go/testdata/imp/imp.pb.go b/protoc-gen-go/testdata/imp/imp.pb.go
index b781ae2..5a5a3b3 100644
--- a/protoc-gen-go/testdata/imp/imp.pb.go
+++ b/protoc-gen-go/testdata/imp/imp.pb.go
@@ -6,6 +6,8 @@
 import proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
 import math "math"
+import imp2 "github.com/golang/protobuf/protoc-gen-go/testdata/imp/imp2"
+import imp3 "github.com/golang/protobuf/protoc-gen-go/testdata/imp/imp3"
 
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
@@ -18,6 +20,67 @@
 // proto package needs to be updated.
 const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 
+// PubliclyImportedMessage from public import imp/imp2/imp2.proto
+type PubliclyImportedMessage imp2.PubliclyImportedMessage
+
+func (m *PubliclyImportedMessage) Reset()         { (*imp2.PubliclyImportedMessage)(m).Reset() }
+func (m *PubliclyImportedMessage) String() string { return (*imp2.PubliclyImportedMessage)(m).String() }
+func (*PubliclyImportedMessage) ProtoMessage()    {}
+func (m *PubliclyImportedMessage) XXX_Unmarshal(buf []byte) error {
+	return (*imp2.PubliclyImportedMessage)(m).XXX_Unmarshal(buf)
+}
+func (m *PubliclyImportedMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return (*imp2.PubliclyImportedMessage)(m).XXX_Marshal(b, deterministic)
+}
+func (m *PubliclyImportedMessage) XXX_Size() int { return (*imp2.PubliclyImportedMessage)(m).XXX_Size() }
+func (m *PubliclyImportedMessage) XXX_DiscardUnknown() {
+	(*imp2.PubliclyImportedMessage)(m).XXX_DiscardUnknown()
+}
+func (m *PubliclyImportedMessage) GetField() int64 {
+	return (*imp2.PubliclyImportedMessage)(m).GetField()
+}
+
+// PubliclyImportedMessage2 from public import imp/imp2/imp2.proto
+type PubliclyImportedMessage2 imp2.PubliclyImportedMessage2
+
+func (m *PubliclyImportedMessage2) Reset() { (*imp2.PubliclyImportedMessage2)(m).Reset() }
+func (m *PubliclyImportedMessage2) String() string {
+	return (*imp2.PubliclyImportedMessage2)(m).String()
+}
+func (*PubliclyImportedMessage2) ProtoMessage() {}
+func (m *PubliclyImportedMessage2) XXX_Unmarshal(buf []byte) error {
+	return (*imp2.PubliclyImportedMessage2)(m).XXX_Unmarshal(buf)
+}
+func (m *PubliclyImportedMessage2) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return (*imp2.PubliclyImportedMessage2)(m).XXX_Marshal(b, deterministic)
+}
+func (m *PubliclyImportedMessage2) XXX_Size() int {
+	return (*imp2.PubliclyImportedMessage2)(m).XXX_Size()
+}
+func (m *PubliclyImportedMessage2) XXX_DiscardUnknown() {
+	(*imp2.PubliclyImportedMessage2)(m).XXX_DiscardUnknown()
+}
+func (m *PubliclyImportedMessage2) GetField() *PubliclyImportedMessage {
+	return (*PubliclyImportedMessage)((*imp2.PubliclyImportedMessage2)(m).GetField())
+}
+
+// PubliclyImportedEnum from public import imp/imp2/imp2.proto
+type PubliclyImportedEnum imp2.PubliclyImportedEnum
+
+var PubliclyImportedEnum_name = imp2.PubliclyImportedEnum_name
+var PubliclyImportedEnum_value = imp2.PubliclyImportedEnum_value
+
+func (x PubliclyImportedEnum) String() string { return (imp2.PubliclyImportedEnum)(x).String() }
+func (x PubliclyImportedEnum) Enum() *PubliclyImportedEnum {
+	return (*PubliclyImportedEnum)((imp2.PubliclyImportedEnum)(x).Enum())
+}
+func (x *PubliclyImportedEnum) UnmarshalJSON(data []byte) error {
+	return (*imp2.PubliclyImportedEnum)(x).UnmarshalJSON(data)
+}
+
+const PubliclyImportedEnum_GLASSES = PubliclyImportedEnum(imp2.PubliclyImportedEnum_GLASSES)
+const PubliclyImportedEnum_HAIR = PubliclyImportedEnum(imp2.PubliclyImportedEnum_HAIR)
+
 type ImportedMessage_Owner int32
 
 const (
@@ -51,15 +114,15 @@
 	return nil
 }
 func (ImportedMessage_Owner) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_imp_81275c260ac30f8b, []int{0, 0}
+	return fileDescriptor_imp_6424de66809c2ae5, []int{0, 0}
 }
 
 type ImportedMessage struct {
 	Field *int64 `protobuf:"varint,1,req,name=field" json:"field,omitempty"`
 	// The forwarded getters for these fields are fiddly to get right.
-	LocalMsg   *ImportedMessage2       `protobuf:"bytes,2,opt,name=local_msg,json=localMsg" json:"local_msg,omitempty"`
-	ForeignMsg *ForeignImportedMessage `protobuf:"bytes,3,opt,name=foreign_msg,json=foreignMsg" json:"foreign_msg,omitempty"`
-	EnumField  *ImportedMessage_Owner  `protobuf:"varint,4,opt,name=enum_field,json=enumField,enum=imp.ImportedMessage_Owner" json:"enum_field,omitempty"`
+	LocalMsg   *ImportedMessage2            `protobuf:"bytes,2,opt,name=local_msg,json=localMsg" json:"local_msg,omitempty"`
+	ForeignMsg *imp3.ForeignImportedMessage `protobuf:"bytes,3,opt,name=foreign_msg,json=foreignMsg" json:"foreign_msg,omitempty"`
+	EnumField  *ImportedMessage_Owner       `protobuf:"varint,4,opt,name=enum_field,json=enumField,enum=imp.ImportedMessage_Owner" json:"enum_field,omitempty"`
 	// Types that are valid to be assigned to Union:
 	//	*ImportedMessage_State
 	Union                        isImportedMessage_Union      `protobuf_oneof:"union"`
@@ -77,7 +140,7 @@
 func (m *ImportedMessage) String() string { return proto.CompactTextString(m) }
 func (*ImportedMessage) ProtoMessage()    {}
 func (*ImportedMessage) Descriptor() ([]byte, []int) {
-	return fileDescriptor_imp_81275c260ac30f8b, []int{0}
+	return fileDescriptor_imp_6424de66809c2ae5, []int{0}
 }
 
 var extRange_ImportedMessage = []proto.ExtensionRange{
@@ -136,7 +199,7 @@
 	return nil
 }
 
-func (m *ImportedMessage) GetForeignMsg() *ForeignImportedMessage {
+func (m *ImportedMessage) GetForeignMsg() *imp3.ForeignImportedMessage {
 	if m != nil {
 		return m.ForeignMsg
 	}
@@ -245,7 +308,7 @@
 func (m *ImportedMessage2) String() string { return proto.CompactTextString(m) }
 func (*ImportedMessage2) ProtoMessage()    {}
 func (*ImportedMessage2) Descriptor() ([]byte, []int) {
-	return fileDescriptor_imp_81275c260ac30f8b, []int{1}
+	return fileDescriptor_imp_6424de66809c2ae5, []int{1}
 }
 func (m *ImportedMessage2) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_ImportedMessage2.Unmarshal(m, b)
@@ -276,7 +339,7 @@
 func (m *ImportedExtendable) String() string { return proto.CompactTextString(m) }
 func (*ImportedExtendable) ProtoMessage()    {}
 func (*ImportedExtendable) Descriptor() ([]byte, []int) {
-	return fileDescriptor_imp_81275c260ac30f8b, []int{2}
+	return fileDescriptor_imp_6424de66809c2ae5, []int{2}
 }
 
 func (m *ImportedExtendable) MarshalJSON() ([]byte, error) {
@@ -319,35 +382,35 @@
 	proto.RegisterEnum("imp.ImportedMessage_Owner", ImportedMessage_Owner_name, ImportedMessage_Owner_value)
 }
 
-func init() { proto.RegisterFile("imp/imp.proto", fileDescriptor_imp_81275c260ac30f8b) }
+func init() { proto.RegisterFile("imp/imp.proto", fileDescriptor_imp_6424de66809c2ae5) }
 
-var fileDescriptor_imp_81275c260ac30f8b = []byte{
-	// 421 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0x4f, 0x8b, 0xd4, 0x30,
-	0x18, 0xc6, 0x4d, 0xff, 0xec, 0xb4, 0xef, 0xe0, 0x5a, 0x82, 0x4a, 0x99, 0xbd, 0x84, 0x9e, 0xea,
-	0xca, 0x76, 0xa0, 0x22, 0xba, 0x8b, 0x17, 0x17, 0x67, 0x71, 0x91, 0xa2, 0xf4, 0xe0, 0x61, 0x2f,
-	0x43, 0x66, 0x9a, 0x89, 0xc5, 0x26, 0x29, 0x4d, 0xaa, 0xee, 0xf7, 0xf0, 0xfb, 0x56, 0x9a, 0xae,
-	0x22, 0xc3, 0xe8, 0xde, 0x9e, 0xe7, 0xe1, 0xf7, 0xe4, 0x4d, 0x9b, 0x17, 0x1e, 0xd6, 0xa2, 0x5d,
-	0xd6, 0xa2, 0xcd, 0xda, 0x4e, 0x19, 0x85, 0xdd, 0x5a, 0xb4, 0x8b, 0xe3, 0xbb, 0x2c, 0x9f, 0xc2,
-	0x3f, 0xfe, 0xc5, 0xe4, 0x93, 0x9f, 0x1e, 0x3c, 0xba, 0x16, 0xad, 0xea, 0x0c, 0xab, 0x0a, 0xa6,
-	0x35, 0xe5, 0x0c, 0x3f, 0x06, 0x7f, 0x57, 0xb3, 0xa6, 0x8a, 0x11, 0x71, 0x52, 0xb7, 0x9c, 0x0c,
-	0xce, 0x21, 0x6c, 0xd4, 0x96, 0x36, 0x6b, 0xa1, 0x79, 0xec, 0x10, 0x94, 0xce, 0xf3, 0x27, 0xd9,
-	0x38, 0x6d, 0xaf, 0x9e, 0x97, 0x81, 0xe5, 0x0a, 0xcd, 0xf1, 0x1b, 0x98, 0xef, 0x54, 0xc7, 0x6a,
-	0x2e, 0x6d, 0xcb, 0xb5, 0xad, 0x13, 0xdb, 0xba, 0x9a, 0xf2, 0xbd, 0x72, 0x09, 0x77, 0xfc, 0xd8,
-	0x3e, 0x07, 0x60, 0xb2, 0x17, 0xeb, 0xe9, 0x32, 0x1e, 0x41, 0xe9, 0x71, 0xbe, 0x38, 0x34, 0x32,
-	0xfb, 0xf8, 0x5d, 0xb2, 0xae, 0x0c, 0x47, 0xfa, 0xca, 0x5e, 0xf6, 0x29, 0xf8, 0xda, 0x50, 0xc3,
-	0xe2, 0x90, 0xa0, 0xd4, 0x7f, 0xff, 0xa0, 0x9c, 0x2c, 0xc6, 0xe0, 0x49, 0x2a, 0x58, 0xec, 0x13,
-	0x37, 0x0d, 0x4b, 0xab, 0x71, 0x06, 0xde, 0x46, 0x69, 0x1d, 0x1f, 0x11, 0xf7, 0x9e, 0x01, 0x96,
-	0xc3, 0xcf, 0xc0, 0x13, 0x4c, 0xa8, 0x78, 0x46, 0xdc, 0x7f, 0xff, 0x03, 0x8b, 0xe0, 0x73, 0x98,
-	0x09, 0xcd, 0xd7, 0x82, 0xb6, 0x71, 0x60, 0x69, 0x72, 0xf0, 0xf4, 0x42, 0xf3, 0x82, 0xb6, 0x2b,
-	0x69, 0xba, 0xdb, 0xf2, 0x48, 0x58, 0xb3, 0xf8, 0x04, 0xf3, 0xbf, 0x62, 0x1c, 0x81, 0xfb, 0x95,
-	0xdd, 0xc6, 0x88, 0xa0, 0x34, 0x2c, 0x47, 0x89, 0x9f, 0x83, 0xff, 0x8d, 0x36, 0x3d, 0xfb, 0xff,
-	0x5b, 0x4c, 0xcc, 0x85, 0xf3, 0x1a, 0x25, 0x27, 0xe0, 0xdb, 0xcf, 0xc0, 0x01, 0x78, 0xef, 0xde,
-	0x7e, 0x5e, 0x45, 0x68, 0x54, 0xc5, 0xf5, 0x87, 0x55, 0xe4, 0x9c, 0x7a, 0xc1, 0x4d, 0xc4, 0x2e,
-	0x67, 0xe0, 0xf7, 0xb2, 0x56, 0x32, 0xc1, 0x10, 0xed, 0x1f, 0x95, 0x24, 0x80, 0x7f, 0x67, 0xab,
-	0x1f, 0x86, 0xc9, 0x8a, 0x6e, 0x1a, 0x76, 0x1a, 0x04, 0x55, 0x34, 0x0c, 0xc3, 0x30, 0xbb, 0x70,
-	0x02, 0x74, 0xf9, 0xea, 0xe6, 0x25, 0xaf, 0xcd, 0x97, 0x7e, 0x93, 0x6d, 0x95, 0x58, 0x72, 0xd5,
-	0x50, 0xc9, 0x97, 0x76, 0xd3, 0x36, 0xfd, 0x6e, 0x12, 0xdb, 0x33, 0xce, 0xe4, 0x19, 0x57, 0x4b,
-	0xc3, 0xb4, 0xa9, 0xa8, 0xa1, 0xe3, 0x3a, 0xfe, 0x0a, 0x00, 0x00, 0xff, 0xff, 0xb1, 0xe4, 0x5b,
-	0xa3, 0xbc, 0x02, 0x00, 0x00,
+var fileDescriptor_imp_6424de66809c2ae5 = []byte{
+	// 427 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x52, 0x4d, 0x6f, 0xd4, 0x30,
+	0x10, 0xad, 0xf3, 0xd1, 0x4d, 0x66, 0x05, 0x44, 0xe6, 0x43, 0xd1, 0xf6, 0x62, 0xe5, 0x14, 0x8a,
+	0x9a, 0x95, 0x82, 0x10, 0xb4, 0xe2, 0x42, 0xc5, 0x56, 0x54, 0x28, 0xa2, 0xca, 0x81, 0x43, 0x2f,
+	0x2b, 0xef, 0xc6, 0x6b, 0x22, 0x62, 0x3b, 0x8a, 0x1d, 0xa0, 0xff, 0x83, 0xff, 0x1b, 0x14, 0xa7,
+	0x20, 0xb4, 0x2a, 0xf4, 0x32, 0x7a, 0xf3, 0xfc, 0xde, 0xcc, 0xd8, 0x1e, 0x78, 0x50, 0x8b, 0x76,
+	0x59, 0x8b, 0x36, 0x6b, 0x3b, 0x65, 0x14, 0x76, 0x6b, 0xd1, 0x2e, 0x1e, 0xdf, 0x72, 0xb9, 0x0d,
+	0xd3, 0xc9, 0x1f, 0xf2, 0xa5, 0x0d, 0x13, 0x99, 0xfc, 0xf4, 0xe0, 0xd1, 0xa5, 0x68, 0x55, 0x67,
+	0x58, 0x55, 0x30, 0xad, 0x29, 0x67, 0xf8, 0x09, 0xf8, 0xbb, 0x9a, 0x35, 0x55, 0x8c, 0x88, 0x93,
+	0xba, 0xe5, 0x94, 0xe0, 0x1c, 0xc2, 0x46, 0x6d, 0x69, 0xb3, 0x16, 0x9a, 0xc7, 0x0e, 0x41, 0xe9,
+	0x3c, 0x7f, 0x9a, 0x8d, 0x7d, 0xf7, 0xec, 0x79, 0x19, 0x58, 0x5d, 0xa1, 0x39, 0x7e, 0x0b, 0xf3,
+	0x9d, 0xea, 0x58, 0xcd, 0xa5, 0x75, 0xb9, 0xd6, 0x75, 0x64, 0x5d, 0x17, 0x13, 0xbf, 0x67, 0x2e,
+	0xe1, 0x56, 0x3f, 0xba, 0x4f, 0x01, 0x98, 0xec, 0xc5, 0x7a, 0x1a, 0xc6, 0x23, 0x28, 0x7d, 0x98,
+	0x2f, 0xee, 0x6a, 0x99, 0x7d, 0xfa, 0x2e, 0x59, 0x57, 0x86, 0xa3, 0xfa, 0xc2, 0x0e, 0xfb, 0x0c,
+	0x7c, 0x6d, 0xa8, 0x61, 0x71, 0x48, 0x50, 0xea, 0x7f, 0x38, 0x28, 0xa7, 0x14, 0x63, 0xf0, 0x24,
+	0x15, 0x2c, 0xf6, 0x89, 0x9b, 0x86, 0xa5, 0xc5, 0x38, 0x03, 0x6f, 0xa3, 0xb4, 0x8e, 0x0f, 0x89,
+	0x7b, 0x4f, 0x03, 0xab, 0xc3, 0xcf, 0xc1, 0x13, 0x4c, 0xa8, 0x78, 0x46, 0xdc, 0x7f, 0xbf, 0x81,
+	0x95, 0xe0, 0x53, 0x98, 0x09, 0xcd, 0xd7, 0x82, 0xb6, 0x71, 0x60, 0xd5, 0xe4, 0xce, 0xea, 0x85,
+	0xe6, 0x05, 0x6d, 0x57, 0xd2, 0x74, 0x37, 0xe5, 0xa1, 0xb0, 0xc9, 0xe2, 0x0a, 0xe6, 0x7f, 0xd1,
+	0x38, 0x02, 0xf7, 0x2b, 0xbb, 0x89, 0x11, 0x41, 0x69, 0x58, 0x8e, 0x10, 0xbf, 0x00, 0xff, 0x1b,
+	0x6d, 0x7a, 0xf6, 0xff, 0xbf, 0x98, 0x34, 0x67, 0xce, 0x1b, 0x94, 0x1c, 0x81, 0x6f, 0xaf, 0x81,
+	0x03, 0xf0, 0xde, 0xbf, 0xfb, 0xbc, 0x8a, 0xd0, 0x88, 0x8a, 0xcb, 0x8f, 0xab, 0xc8, 0x39, 0xf6,
+	0x82, 0xeb, 0x88, 0x9d, 0xcf, 0xc0, 0xef, 0x65, 0xad, 0x64, 0x82, 0x21, 0xda, 0x2f, 0x95, 0x24,
+	0x80, 0x7f, 0x73, 0xab, 0x1f, 0x86, 0xc9, 0x8a, 0x6e, 0x1a, 0x76, 0x1c, 0x04, 0x55, 0x34, 0x0c,
+	0xc3, 0x30, 0x3b, 0x73, 0x02, 0x74, 0xfe, 0xfa, 0xfa, 0x15, 0xaf, 0xcd, 0x97, 0x7e, 0x93, 0x6d,
+	0x95, 0x58, 0x72, 0xd5, 0x50, 0xc9, 0x97, 0x76, 0xd3, 0x36, 0xfd, 0x6e, 0x02, 0xdb, 0x13, 0xce,
+	0xe4, 0x09, 0x57, 0x4b, 0xc3, 0xb4, 0xa9, 0xa8, 0xa1, 0xe3, 0x3a, 0x5e, 0x1d, 0xfc, 0x0a, 0x00,
+	0x00, 0xff, 0xff, 0xe7, 0x7a, 0x0f, 0x3a, 0xc8, 0x02, 0x00, 0x00,
 }
diff --git a/protoc-gen-go/testdata/imp/imp.proto b/protoc-gen-go/testdata/imp/imp.proto
index 924b99d..43f88ba 100644
--- a/protoc-gen-go/testdata/imp/imp.proto
+++ b/protoc-gen-go/testdata/imp/imp.proto
@@ -35,8 +35,8 @@
 
 option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/imp";
 
-import "imp/imp2.proto";
-import "imp/imp3.proto";
+import public "imp/imp2/imp2.proto";
+import "imp/imp3/imp3.proto";
 
 message ImportedMessage {
   required int64 field = 1;
diff --git a/protoc-gen-go/testdata/imp/imp2.pb.go b/protoc-gen-go/testdata/imp/imp2.pb.go
deleted file mode 100644
index a9d531a..0000000
--- a/protoc-gen-go/testdata/imp/imp2.pb.go
+++ /dev/null
@@ -1,115 +0,0 @@
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// source: imp/imp2.proto
-
-package imp // import "github.com/golang/protobuf/protoc-gen-go/testdata/imp"
-
-import proto "github.com/golang/protobuf/proto"
-import fmt "fmt"
-import math "math"
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
-
-type PubliclyImportedEnum int32
-
-const (
-	PubliclyImportedEnum_GLASSES PubliclyImportedEnum = 1
-	PubliclyImportedEnum_HAIR    PubliclyImportedEnum = 2
-)
-
-var PubliclyImportedEnum_name = map[int32]string{
-	1: "GLASSES",
-	2: "HAIR",
-}
-var PubliclyImportedEnum_value = map[string]int32{
-	"GLASSES": 1,
-	"HAIR":    2,
-}
-
-func (x PubliclyImportedEnum) Enum() *PubliclyImportedEnum {
-	p := new(PubliclyImportedEnum)
-	*p = x
-	return p
-}
-func (x PubliclyImportedEnum) String() string {
-	return proto.EnumName(PubliclyImportedEnum_name, int32(x))
-}
-func (x *PubliclyImportedEnum) UnmarshalJSON(data []byte) error {
-	value, err := proto.UnmarshalJSONEnum(PubliclyImportedEnum_value, data, "PubliclyImportedEnum")
-	if err != nil {
-		return err
-	}
-	*x = PubliclyImportedEnum(value)
-	return nil
-}
-func (PubliclyImportedEnum) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_imp2_dcbceb16a8ff78d7, []int{0}
-}
-
-type PubliclyImportedMessage struct {
-	Field                *int64   `protobuf:"varint,1,opt,name=field" json:"field,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
-
-func (m *PubliclyImportedMessage) Reset()         { *m = PubliclyImportedMessage{} }
-func (m *PubliclyImportedMessage) String() string { return proto.CompactTextString(m) }
-func (*PubliclyImportedMessage) ProtoMessage()    {}
-func (*PubliclyImportedMessage) Descriptor() ([]byte, []int) {
-	return fileDescriptor_imp2_dcbceb16a8ff78d7, []int{0}
-}
-func (m *PubliclyImportedMessage) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_PubliclyImportedMessage.Unmarshal(m, b)
-}
-func (m *PubliclyImportedMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_PubliclyImportedMessage.Marshal(b, m, deterministic)
-}
-func (dst *PubliclyImportedMessage) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_PubliclyImportedMessage.Merge(dst, src)
-}
-func (m *PubliclyImportedMessage) XXX_Size() int {
-	return xxx_messageInfo_PubliclyImportedMessage.Size(m)
-}
-func (m *PubliclyImportedMessage) XXX_DiscardUnknown() {
-	xxx_messageInfo_PubliclyImportedMessage.DiscardUnknown(m)
-}
-
-var xxx_messageInfo_PubliclyImportedMessage proto.InternalMessageInfo
-
-func (m *PubliclyImportedMessage) GetField() int64 {
-	if m != nil && m.Field != nil {
-		return *m.Field
-	}
-	return 0
-}
-
-func init() {
-	proto.RegisterType((*PubliclyImportedMessage)(nil), "imp.PubliclyImportedMessage")
-	proto.RegisterEnum("imp.PubliclyImportedEnum", PubliclyImportedEnum_name, PubliclyImportedEnum_value)
-}
-
-func init() { proto.RegisterFile("imp/imp2.proto", fileDescriptor_imp2_dcbceb16a8ff78d7) }
-
-var fileDescriptor_imp2_dcbceb16a8ff78d7 = []byte{
-	// 171 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcb, 0xcc, 0x2d, 0xd0,
-	0xcf, 0xcc, 0x2d, 0x30, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xce, 0xcc, 0x2d, 0x50,
-	0xd2, 0xe7, 0x12, 0x0f, 0x28, 0x4d, 0xca, 0xc9, 0x4c, 0xce, 0xa9, 0xf4, 0xcc, 0x2d, 0xc8, 0x2f,
-	0x2a, 0x49, 0x4d, 0xf1, 0x4d, 0x2d, 0x2e, 0x4e, 0x4c, 0x4f, 0x15, 0x12, 0xe1, 0x62, 0x4d, 0xcb,
-	0x4c, 0xcd, 0x49, 0x91, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x0e, 0x82, 0x70, 0xb4, 0x74, 0xb9, 0x44,
-	0xd0, 0x35, 0xb8, 0xe6, 0x95, 0xe6, 0x0a, 0x71, 0x73, 0xb1, 0xbb, 0xfb, 0x38, 0x06, 0x07, 0xbb,
-	0x06, 0x0b, 0x30, 0x0a, 0x71, 0x70, 0xb1, 0x78, 0x38, 0x7a, 0x06, 0x09, 0x30, 0x39, 0x99, 0x47,
-	0x99, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0xa7, 0xe7, 0xe7, 0x24,
-	0xe6, 0xa5, 0xeb, 0x83, 0xed, 0x4f, 0x2a, 0x4d, 0x83, 0x30, 0x92, 0x75, 0xd3, 0x53, 0xf3, 0x74,
-	0xd3, 0xf3, 0xf5, 0x4b, 0x52, 0x8b, 0x4b, 0x52, 0x12, 0x4b, 0x12, 0x41, 0x8e, 0x04, 0x04, 0x00,
-	0x00, 0xff, 0xff, 0x32, 0x18, 0x4d, 0x15, 0xae, 0x00, 0x00, 0x00,
-}
diff --git a/protoc-gen-go/testdata/imp/imp2/imp2.pb.go b/protoc-gen-go/testdata/imp/imp2/imp2.pb.go
new file mode 100644
index 0000000..048bc0a
--- /dev/null
+++ b/protoc-gen-go/testdata/imp/imp2/imp2.pb.go
@@ -0,0 +1,156 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: imp/imp2/imp2.proto
+
+package imp2 // import "github.com/golang/protobuf/protoc-gen-go/testdata/imp/imp2"
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type PubliclyImportedEnum int32
+
+const (
+	PubliclyImportedEnum_GLASSES PubliclyImportedEnum = 1
+	PubliclyImportedEnum_HAIR    PubliclyImportedEnum = 2
+)
+
+var PubliclyImportedEnum_name = map[int32]string{
+	1: "GLASSES",
+	2: "HAIR",
+}
+var PubliclyImportedEnum_value = map[string]int32{
+	"GLASSES": 1,
+	"HAIR":    2,
+}
+
+func (x PubliclyImportedEnum) Enum() *PubliclyImportedEnum {
+	p := new(PubliclyImportedEnum)
+	*p = x
+	return p
+}
+func (x PubliclyImportedEnum) String() string {
+	return proto.EnumName(PubliclyImportedEnum_name, int32(x))
+}
+func (x *PubliclyImportedEnum) UnmarshalJSON(data []byte) error {
+	value, err := proto.UnmarshalJSONEnum(PubliclyImportedEnum_value, data, "PubliclyImportedEnum")
+	if err != nil {
+		return err
+	}
+	*x = PubliclyImportedEnum(value)
+	return nil
+}
+func (PubliclyImportedEnum) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_imp2_a81b5fa1a6dca420, []int{0}
+}
+
+type PubliclyImportedMessage struct {
+	Field                *int64   `protobuf:"varint,1,opt,name=field" json:"field,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *PubliclyImportedMessage) Reset()         { *m = PubliclyImportedMessage{} }
+func (m *PubliclyImportedMessage) String() string { return proto.CompactTextString(m) }
+func (*PubliclyImportedMessage) ProtoMessage()    {}
+func (*PubliclyImportedMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_imp2_a81b5fa1a6dca420, []int{0}
+}
+func (m *PubliclyImportedMessage) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_PubliclyImportedMessage.Unmarshal(m, b)
+}
+func (m *PubliclyImportedMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_PubliclyImportedMessage.Marshal(b, m, deterministic)
+}
+func (dst *PubliclyImportedMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PubliclyImportedMessage.Merge(dst, src)
+}
+func (m *PubliclyImportedMessage) XXX_Size() int {
+	return xxx_messageInfo_PubliclyImportedMessage.Size(m)
+}
+func (m *PubliclyImportedMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_PubliclyImportedMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PubliclyImportedMessage proto.InternalMessageInfo
+
+func (m *PubliclyImportedMessage) GetField() int64 {
+	if m != nil && m.Field != nil {
+		return *m.Field
+	}
+	return 0
+}
+
+type PubliclyImportedMessage2 struct {
+	Field                *PubliclyImportedMessage `protobuf:"bytes,1,opt,name=field" json:"field,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}                 `json:"-"`
+	XXX_unrecognized     []byte                   `json:"-"`
+	XXX_sizecache        int32                    `json:"-"`
+}
+
+func (m *PubliclyImportedMessage2) Reset()         { *m = PubliclyImportedMessage2{} }
+func (m *PubliclyImportedMessage2) String() string { return proto.CompactTextString(m) }
+func (*PubliclyImportedMessage2) ProtoMessage()    {}
+func (*PubliclyImportedMessage2) Descriptor() ([]byte, []int) {
+	return fileDescriptor_imp2_a81b5fa1a6dca420, []int{1}
+}
+func (m *PubliclyImportedMessage2) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_PubliclyImportedMessage2.Unmarshal(m, b)
+}
+func (m *PubliclyImportedMessage2) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_PubliclyImportedMessage2.Marshal(b, m, deterministic)
+}
+func (dst *PubliclyImportedMessage2) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PubliclyImportedMessage2.Merge(dst, src)
+}
+func (m *PubliclyImportedMessage2) XXX_Size() int {
+	return xxx_messageInfo_PubliclyImportedMessage2.Size(m)
+}
+func (m *PubliclyImportedMessage2) XXX_DiscardUnknown() {
+	xxx_messageInfo_PubliclyImportedMessage2.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PubliclyImportedMessage2 proto.InternalMessageInfo
+
+func (m *PubliclyImportedMessage2) GetField() *PubliclyImportedMessage {
+	if m != nil {
+		return m.Field
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterType((*PubliclyImportedMessage)(nil), "imp.PubliclyImportedMessage")
+	proto.RegisterType((*PubliclyImportedMessage2)(nil), "imp.PubliclyImportedMessage2")
+	proto.RegisterEnum("imp.PubliclyImportedEnum", PubliclyImportedEnum_name, PubliclyImportedEnum_value)
+}
+
+func init() { proto.RegisterFile("imp/imp2/imp2.proto", fileDescriptor_imp2_a81b5fa1a6dca420) }
+
+var fileDescriptor_imp2_a81b5fa1a6dca420 = []byte{
+	// 198 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xce, 0xcc, 0x2d, 0xd0,
+	0xcf, 0xcc, 0x2d, 0x30, 0x02, 0x13, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0xcc, 0x99, 0xb9,
+	0x05, 0x4a, 0xfa, 0x5c, 0xe2, 0x01, 0xa5, 0x49, 0x39, 0x99, 0xc9, 0x39, 0x95, 0x9e, 0xb9, 0x05,
+	0xf9, 0x45, 0x25, 0xa9, 0x29, 0xbe, 0xa9, 0xc5, 0xc5, 0x89, 0xe9, 0xa9, 0x42, 0x22, 0x5c, 0xac,
+	0x69, 0x99, 0xa9, 0x39, 0x29, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x10, 0x8e, 0x92, 0x1f,
+	0x97, 0x04, 0x0e, 0x0d, 0x46, 0x42, 0x46, 0xc8, 0x3a, 0xb8, 0x8d, 0x64, 0xf4, 0x32, 0x73, 0x0b,
+	0xf4, 0x70, 0xa8, 0x86, 0x9a, 0xa7, 0xa5, 0xcb, 0x25, 0x82, 0xae, 0xc2, 0x35, 0xaf, 0x34, 0x57,
+	0x88, 0x9b, 0x8b, 0xdd, 0xdd, 0xc7, 0x31, 0x38, 0xd8, 0x35, 0x58, 0x80, 0x51, 0x88, 0x83, 0x8b,
+	0xc5, 0xc3, 0xd1, 0x33, 0x48, 0x80, 0xc9, 0xc9, 0x26, 0xca, 0x2a, 0x3d, 0xb3, 0x24, 0xa3, 0x34,
+	0x49, 0x2f, 0x39, 0x3f, 0x57, 0x3f, 0x3d, 0x3f, 0x27, 0x31, 0x2f, 0x5d, 0x1f, 0xec, 0x9f, 0xa4,
+	0xd2, 0x34, 0x08, 0x23, 0x59, 0x37, 0x3d, 0x35, 0x4f, 0x37, 0x3d, 0x5f, 0xbf, 0x24, 0xb5, 0xb8,
+	0x24, 0x25, 0xb1, 0x24, 0x51, 0x1f, 0xe6, 0x7b, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xcb,
+	0xbc, 0x81, 0x08, 0x01, 0x00, 0x00,
+}
diff --git a/protoc-gen-go/testdata/imp/imp2.proto b/protoc-gen-go/testdata/imp/imp2/imp2.proto
similarity index 94%
rename from protoc-gen-go/testdata/imp/imp2.proto
rename to protoc-gen-go/testdata/imp/imp2/imp2.proto
index ee67fb9..acf4088 100644
--- a/protoc-gen-go/testdata/imp/imp2.proto
+++ b/protoc-gen-go/testdata/imp/imp2/imp2.proto
@@ -33,12 +33,16 @@
 
 package imp;
 
-option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/imp";
+option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/imp/imp2";
 
 message PubliclyImportedMessage {
   optional int64 field = 1;
 }
 
+message PubliclyImportedMessage2 {
+  optional PubliclyImportedMessage field = 1;
+}
+
 enum PubliclyImportedEnum {
   GLASSES = 1;
   HAIR = 2;
diff --git a/protoc-gen-go/testdata/imp/imp3.pb.go b/protoc-gen-go/testdata/imp/imp3/imp3.pb.go
similarity index 65%
rename from protoc-gen-go/testdata/imp/imp3.pb.go
rename to protoc-gen-go/testdata/imp/imp3/imp3.pb.go
index e7f5697..1d28339 100644
--- a/protoc-gen-go/testdata/imp/imp3.pb.go
+++ b/protoc-gen-go/testdata/imp/imp3/imp3.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
-// source: imp/imp3.proto
+// source: imp/imp3/imp3.proto
 
-package imp // import "github.com/golang/protobuf/protoc-gen-go/testdata/imp"
+package imp3 // import "github.com/golang/protobuf/protoc-gen-go/testdata/imp/imp3"
 
 import proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
@@ -29,7 +29,7 @@
 func (m *ForeignImportedMessage) String() string { return proto.CompactTextString(m) }
 func (*ForeignImportedMessage) ProtoMessage()    {}
 func (*ForeignImportedMessage) Descriptor() ([]byte, []int) {
-	return fileDescriptor_imp3_dbacc1715de7e782, []int{0}
+	return fileDescriptor_imp3_4aae87d6f1c23d12, []int{0}
 }
 func (m *ForeignImportedMessage) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_ForeignImportedMessage.Unmarshal(m, b)
@@ -60,17 +60,17 @@
 	proto.RegisterType((*ForeignImportedMessage)(nil), "imp.ForeignImportedMessage")
 }
 
-func init() { proto.RegisterFile("imp/imp3.proto", fileDescriptor_imp3_dbacc1715de7e782) }
+func init() { proto.RegisterFile("imp/imp3/imp3.proto", fileDescriptor_imp3_4aae87d6f1c23d12) }
 
-var fileDescriptor_imp3_dbacc1715de7e782 = []byte{
-	// 137 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcb, 0xcc, 0x2d, 0xd0,
-	0xcf, 0xcc, 0x2d, 0x30, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xce, 0xcc, 0x2d, 0x50,
-	0xd2, 0xe3, 0x12, 0x73, 0xcb, 0x2f, 0x4a, 0xcd, 0x4c, 0xcf, 0xf3, 0xcc, 0x2d, 0xc8, 0x2f, 0x2a,
-	0x49, 0x4d, 0xf1, 0x4d, 0x2d, 0x2e, 0x4e, 0x4c, 0x4f, 0x15, 0x12, 0xe1, 0x62, 0x2d, 0x29, 0x4d,
-	0x4a, 0x2d, 0x92, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x82, 0x70, 0x9c, 0xcc, 0xa3, 0x4c, 0xd3,
-	0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0xd3, 0xf3, 0x73, 0x12, 0xf3, 0xd2,
-	0xf5, 0xc1, 0xe6, 0x25, 0x95, 0xa6, 0x41, 0x18, 0xc9, 0xba, 0xe9, 0xa9, 0x79, 0xba, 0xe9, 0xf9,
-	0xfa, 0x25, 0xa9, 0xc5, 0x25, 0x29, 0x89, 0x25, 0x89, 0x20, 0x4b, 0x01, 0x01, 0x00, 0x00, 0xff,
-	0xff, 0xa9, 0xbf, 0xbe, 0xdc, 0x7e, 0x00, 0x00, 0x00,
+var fileDescriptor_imp3_4aae87d6f1c23d12 = []byte{
+	// 139 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xce, 0xcc, 0x2d, 0xd0,
+	0xcf, 0xcc, 0x2d, 0x30, 0x06, 0x13, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0xcc, 0x99, 0xb9,
+	0x05, 0x4a, 0x7a, 0x5c, 0x62, 0x6e, 0xf9, 0x45, 0xa9, 0x99, 0xe9, 0x79, 0x9e, 0xb9, 0x05, 0xf9,
+	0x45, 0x25, 0xa9, 0x29, 0xbe, 0xa9, 0xc5, 0xc5, 0x89, 0xe9, 0xa9, 0x42, 0x22, 0x5c, 0xac, 0x25,
+	0xa5, 0x49, 0xa9, 0x45, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x10, 0x8e, 0x93, 0x4d, 0x94,
+	0x55, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x7a, 0x7e, 0x4e, 0x62,
+	0x5e, 0xba, 0x3e, 0xd8, 0xbc, 0xa4, 0xd2, 0x34, 0x08, 0x23, 0x59, 0x37, 0x3d, 0x35, 0x4f, 0x37,
+	0x3d, 0x5f, 0xbf, 0x24, 0xb5, 0xb8, 0x24, 0x25, 0xb1, 0x24, 0x51, 0x1f, 0x66, 0x3b, 0x20, 0x00,
+	0x00, 0xff, 0xff, 0xda, 0xb9, 0x43, 0xe2, 0x88, 0x00, 0x00, 0x00,
 }
diff --git a/protoc-gen-go/testdata/imp/imp3.proto b/protoc-gen-go/testdata/imp/imp3/imp3.proto
similarity index 98%
rename from protoc-gen-go/testdata/imp/imp3.proto
rename to protoc-gen-go/testdata/imp/imp3/imp3.proto
index 2aed1d5..a322a74 100644
--- a/protoc-gen-go/testdata/imp/imp3.proto
+++ b/protoc-gen-go/testdata/imp/imp3/imp3.proto
@@ -33,7 +33,7 @@
 
 package imp;
 
-option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/imp";
+option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/imp/imp3";
 
 message ForeignImportedMessage {
   optional string tuber = 1;
diff --git a/protoc-gen-go/testdata/imports/test_a_1/m1.pb.go b/protoc-gen-go/testdata/imports/test_a_1/m1.pb.go
index cc5f7c3..82ec35e 100644
--- a/protoc-gen-go/testdata/imports/test_a_1/m1.pb.go
+++ b/protoc-gen-go/testdata/imports/test_a_1/m1.pb.go
@@ -18,6 +18,26 @@
 // proto package needs to be updated.
 const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 
+type E1 int32
+
+const (
+	E1_E1_ZERO E1 = 0
+)
+
+var E1_name = map[int32]string{
+	0: "E1_ZERO",
+}
+var E1_value = map[string]int32{
+	"E1_ZERO": 0,
+}
+
+func (x E1) String() string {
+	return proto.EnumName(E1_name, int32(x))
+}
+func (E1) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_m1_56a2598431d21e61, []int{0}
+}
+
 type M1 struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -28,7 +48,7 @@
 func (m *M1) String() string { return proto.CompactTextString(m) }
 func (*M1) ProtoMessage()    {}
 func (*M1) Descriptor() ([]byte, []int) {
-	return fileDescriptor_m1_4abc85f8d0361bef, []int{0}
+	return fileDescriptor_m1_56a2598431d21e61, []int{0}
 }
 func (m *M1) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_M1.Unmarshal(m, b)
@@ -48,20 +68,63 @@
 
 var xxx_messageInfo_M1 proto.InternalMessageInfo
 
-func init() {
-	proto.RegisterType((*M1)(nil), "test.a.M1")
+type M1_1 struct {
+	M1                   *M1      `protobuf:"bytes,1,opt,name=m1" json:"m1,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
 }
 
-func init() { proto.RegisterFile("imports/test_a_1/m1.proto", fileDescriptor_m1_4abc85f8d0361bef) }
+func (m *M1_1) Reset()         { *m = M1_1{} }
+func (m *M1_1) String() string { return proto.CompactTextString(m) }
+func (*M1_1) ProtoMessage()    {}
+func (*M1_1) Descriptor() ([]byte, []int) {
+	return fileDescriptor_m1_56a2598431d21e61, []int{1}
+}
+func (m *M1_1) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_M1_1.Unmarshal(m, b)
+}
+func (m *M1_1) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_M1_1.Marshal(b, m, deterministic)
+}
+func (dst *M1_1) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_M1_1.Merge(dst, src)
+}
+func (m *M1_1) XXX_Size() int {
+	return xxx_messageInfo_M1_1.Size(m)
+}
+func (m *M1_1) XXX_DiscardUnknown() {
+	xxx_messageInfo_M1_1.DiscardUnknown(m)
+}
 
-var fileDescriptor_m1_4abc85f8d0361bef = []byte{
-	// 114 bytes of a gzipped FileDescriptorProto
+var xxx_messageInfo_M1_1 proto.InternalMessageInfo
+
+func (m *M1_1) GetM1() *M1 {
+	if m != nil {
+		return m.M1
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterType((*M1)(nil), "test.a.M1")
+	proto.RegisterType((*M1_1)(nil), "test.a.M1_1")
+	proto.RegisterEnum("test.a.E1", E1_name, E1_value)
+}
+
+func init() { proto.RegisterFile("imports/test_a_1/m1.proto", fileDescriptor_m1_56a2598431d21e61) }
+
+var fileDescriptor_m1_56a2598431d21e61 = []byte{
+	// 165 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcc, 0xcc, 0x2d, 0xc8,
 	0x2f, 0x2a, 0x29, 0xd6, 0x2f, 0x49, 0x2d, 0x2e, 0x89, 0x4f, 0x8c, 0x37, 0xd4, 0xcf, 0x35, 0xd4,
 	0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x03, 0x09, 0xe9, 0x25, 0x2a, 0xb1, 0x70, 0x31, 0xf9,
-	0x1a, 0x3a, 0xb9, 0x44, 0x39, 0xa5, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea,
-	0xa7, 0xe7, 0xe7, 0x24, 0xe6, 0xa5, 0xeb, 0x83, 0x15, 0x26, 0x95, 0xa6, 0x41, 0x18, 0xc9, 0xba,
-	0xe9, 0xa9, 0x79, 0xba, 0xe9, 0xf9, 0x60, 0xb3, 0x52, 0x12, 0x4b, 0x12, 0xf5, 0xd1, 0x0d, 0x4f,
-	0x62, 0x03, 0x2b, 0x34, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x17, 0x7d, 0xab, 0xd8, 0x77, 0x00,
-	0x00, 0x00,
+	0x1a, 0x2a, 0x29, 0x71, 0xb1, 0xf8, 0x1a, 0xc6, 0x1b, 0x0a, 0x49, 0x71, 0x31, 0xe5, 0x1a, 0x4a,
+	0x30, 0x2a, 0x30, 0x6a, 0x70, 0x1b, 0x71, 0xe9, 0x41, 0x94, 0xe8, 0xf9, 0x1a, 0x06, 0x31, 0xe5,
+	0x1a, 0x6a, 0x09, 0x72, 0x31, 0xb9, 0x1a, 0x0a, 0x71, 0x73, 0xb1, 0xbb, 0x1a, 0xc6, 0x47, 0xb9,
+	0x06, 0xf9, 0x0b, 0x30, 0x38, 0xb9, 0x44, 0x39, 0xa5, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25,
+	0xe7, 0xe7, 0xea, 0xa7, 0xe7, 0xe7, 0x24, 0xe6, 0xa5, 0xeb, 0x83, 0xcd, 0x4f, 0x2a, 0x4d, 0x83,
+	0x30, 0x92, 0x75, 0xd3, 0x53, 0xf3, 0x74, 0xd3, 0xf3, 0xc1, 0x4e, 0x48, 0x49, 0x2c, 0x49, 0xd4,
+	0x47, 0x77, 0x53, 0x12, 0x1b, 0x58, 0xa1, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xae, 0xc9,
+	0xcd, 0xae, 0x00, 0x00, 0x00,
 }
diff --git a/protoc-gen-go/testdata/imports/test_a_1/m1.proto b/protoc-gen-go/testdata/imports/test_a_1/m1.proto
index 65bd945..da54c1e 100644
--- a/protoc-gen-go/testdata/imports/test_a_1/m1.proto
+++ b/protoc-gen-go/testdata/imports/test_a_1/m1.proto
@@ -32,4 +32,13 @@
 syntax = "proto3";
 package test.a;
 option go_package = "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_1";
+
 message M1 {}
+
+message M1_1 {
+  M1 m1 = 1;
+}
+
+enum E1 {
+  E1_ZERO = 0;
+}
diff --git a/protoc-gen-go/testdata/imports/test_import_public.pb.go b/protoc-gen-go/testdata/imports/test_import_public.pb.go
index 2349b1a..3725e05 100644
--- a/protoc-gen-go/testdata/imports/test_import_public.pb.go
+++ b/protoc-gen-go/testdata/imports/test_import_public.pb.go
@@ -32,8 +32,33 @@
 func (m *M1) XXX_Size() int       { return (*test_a_1.M1)(m).XXX_Size() }
 func (m *M1) XXX_DiscardUnknown() { (*test_a_1.M1)(m).XXX_DiscardUnknown() }
 
+// M1_1 from public import imports/test_a_1/m1.proto
+type M1_1 test_a_1.M1_1
+
+func (m *M1_1) Reset()                         { (*test_a_1.M1_1)(m).Reset() }
+func (m *M1_1) String() string                 { return (*test_a_1.M1_1)(m).String() }
+func (*M1_1) ProtoMessage()                    {}
+func (m *M1_1) XXX_Unmarshal(buf []byte) error { return (*test_a_1.M1_1)(m).XXX_Unmarshal(buf) }
+func (m *M1_1) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return (*test_a_1.M1_1)(m).XXX_Marshal(b, deterministic)
+}
+func (m *M1_1) XXX_Size() int       { return (*test_a_1.M1_1)(m).XXX_Size() }
+func (m *M1_1) XXX_DiscardUnknown() { (*test_a_1.M1_1)(m).XXX_DiscardUnknown() }
+func (m *M1_1) GetM1() *M1          { return (*M1)((*test_a_1.M1_1)(m).GetM1()) }
+
+// E1 from public import imports/test_a_1/m1.proto
+type E1 test_a_1.E1
+
+var E1_name = test_a_1.E1_name
+var E1_value = test_a_1.E1_value
+
+func (x E1) String() string { return (test_a_1.E1)(x).String() }
+
+const E1_E1_ZERO = E1(test_a_1.E1_E1_ZERO)
+
 type Public struct {
-	F                    *test_a_1.M1 `protobuf:"bytes,1,opt,name=f" json:"f,omitempty"`
+	M1                   *test_a_1.M1 `protobuf:"bytes,1,opt,name=m1" json:"m1,omitempty"`
+	E1                   test_a_1.E1  `protobuf:"varint,2,opt,name=e1,enum=test.a.E1" json:"e1,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
 	XXX_unrecognized     []byte       `json:"-"`
 	XXX_sizecache        int32        `json:"-"`
@@ -43,7 +68,7 @@
 func (m *Public) String() string { return proto.CompactTextString(m) }
 func (*Public) ProtoMessage()    {}
 func (*Public) Descriptor() ([]byte, []int) {
-	return fileDescriptor_test_import_public_592f461eca0812f7, []int{0}
+	return fileDescriptor_test_import_public_b5b1d653c96016f3, []int{0}
 }
 func (m *Public) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_Public.Unmarshal(m, b)
@@ -63,31 +88,39 @@
 
 var xxx_messageInfo_Public proto.InternalMessageInfo
 
-func (m *Public) GetF() *test_a_1.M1 {
+func (m *Public) GetM1() *test_a_1.M1 {
 	if m != nil {
-		return m.F
+		return m.M1
 	}
 	return nil
 }
 
+func (m *Public) GetE1() test_a_1.E1 {
+	if m != nil {
+		return m.E1
+	}
+	return test_a_1.E1_E1_ZERO
+}
+
 func init() {
 	proto.RegisterType((*Public)(nil), "test.Public")
 }
 
 func init() {
-	proto.RegisterFile("imports/test_import_public.proto", fileDescriptor_test_import_public_592f461eca0812f7)
+	proto.RegisterFile("imports/test_import_public.proto", fileDescriptor_test_import_public_b5b1d653c96016f3)
 }
 
-var fileDescriptor_test_import_public_592f461eca0812f7 = []byte{
-	// 154 bytes of a gzipped FileDescriptorProto
+var fileDescriptor_test_import_public_b5b1d653c96016f3 = []byte{
+	// 174 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xc8, 0xcc, 0x2d, 0xc8,
 	0x2f, 0x2a, 0x29, 0xd6, 0x2f, 0x49, 0x2d, 0x2e, 0x89, 0x87, 0x70, 0xe2, 0x0b, 0x4a, 0x93, 0x72,
 	0x32, 0x93, 0xf5, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, 0x85, 0x58, 0x40, 0x32, 0x52, 0x92, 0x28, 0xea,
-	0x12, 0xe3, 0x0d, 0xf5, 0x73, 0x0d, 0x21, 0x0a, 0x94, 0x94, 0xb8, 0xd8, 0x02, 0xc0, 0x1a, 0x84,
-	0x24, 0xb8, 0x18, 0xd3, 0x24, 0x18, 0x15, 0x18, 0x35, 0xb8, 0x8d, 0xb8, 0xf4, 0x40, 0x0a, 0xf5,
-	0x12, 0xf5, 0x7c, 0x0d, 0x83, 0x18, 0xd3, 0x9c, 0xac, 0xa3, 0x2c, 0xd3, 0x33, 0x4b, 0x32, 0x4a,
-	0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0xd3, 0xf3, 0x73, 0x12, 0xf3, 0xd2, 0xf5, 0xc1, 0xda, 0x93,
-	0x4a, 0xd3, 0x20, 0x8c, 0x64, 0xdd, 0xf4, 0xd4, 0x3c, 0xdd, 0xf4, 0x7c, 0xb0, 0x0d, 0x29, 0x89,
-	0x25, 0x89, 0xfa, 0x50, 0x2b, 0x03, 0x18, 0x92, 0xd8, 0xc0, 0x2a, 0x8c, 0x01, 0x01, 0x00, 0x00,
-	0xff, 0xff, 0x2d, 0x78, 0xaa, 0x84, 0xae, 0x00, 0x00, 0x00,
+	0x12, 0xe3, 0x0d, 0xf5, 0x73, 0x0d, 0x21, 0x0a, 0x94, 0x1c, 0xb8, 0xd8, 0x02, 0xc0, 0x1a, 0x84,
+	0xa4, 0xb8, 0x98, 0x72, 0x0d, 0x25, 0x18, 0x15, 0x18, 0x35, 0xb8, 0x8d, 0xb8, 0xf4, 0x40, 0x2a,
+	0xf5, 0x12, 0xf5, 0x7c, 0x0d, 0x83, 0x98, 0x72, 0x0d, 0x41, 0x72, 0xa9, 0x86, 0x12, 0x4c, 0x0a,
+	0x8c, 0x1a, 0x7c, 0x08, 0x39, 0x57, 0xc3, 0x20, 0xa6, 0x54, 0x43, 0x27, 0xeb, 0x28, 0xcb, 0xf4,
+	0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0xf4, 0xfc, 0x9c, 0xc4, 0xbc, 0x74,
+	0x7d, 0xb0, 0xe1, 0x49, 0xa5, 0x69, 0x10, 0x46, 0xb2, 0x6e, 0x7a, 0x6a, 0x9e, 0x6e, 0x7a, 0x3e,
+	0xd8, 0xfe, 0x94, 0xc4, 0x92, 0x44, 0x7d, 0xa8, 0x83, 0x02, 0x18, 0x92, 0xd8, 0xc0, 0x2a, 0x8c,
+	0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x65, 0x95, 0x6f, 0xe5, 0xcc, 0x00, 0x00, 0x00,
 }
diff --git a/protoc-gen-go/testdata/imports/test_import_public.proto b/protoc-gen-go/testdata/imports/test_import_public.proto
index f651c6d..7130cd8 100644
--- a/protoc-gen-go/testdata/imports/test_import_public.proto
+++ b/protoc-gen-go/testdata/imports/test_import_public.proto
@@ -38,5 +38,6 @@
 import public "imports/test_a_1/m1.proto";
 
 message Public {
-  test.a.M1 f = 1;
+  test.a.M1 m1 = 1;
+  test.a.E1 e1 = 2;
 }
diff --git a/protoc-gen-go/testdata/main_test.go b/protoc-gen-go/testdata/main_test.go
index 7ec1f2d..87ee168 100644
--- a/protoc-gen-go/testdata/main_test.go
+++ b/protoc-gen-go/testdata/main_test.go
@@ -36,6 +36,7 @@
 import (
 	"testing"
 
+	imppb "github.com/golang/protobuf/protoc-gen-go/testdata/imp"
 	importspb "github.com/golang/protobuf/protoc-gen-go/testdata/imports"
 	multipb "github.com/golang/protobuf/protoc-gen-go/testdata/multi"
 	mytestpb "github.com/golang/protobuf/protoc-gen-go/testdata/my_test"
@@ -45,4 +46,5 @@
 	_ = &multipb.Multi1{}
 	_ = &mytestpb.Request{}
 	_ = &importspb.All{}
+	_ = &imppb.ImportedMessage{}
 }