proto: enable/disable fast path with build tags

Remove the Reflection field from MarshalOptions and UnmarshalOptions.
Disable the fast path and use the reflection-based implementation when
the 'protoreflect' build tag is set.

Change-Id: Ic674e3af67501de27fb03ec2712fbed40eae7fef
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/170896
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/integration_test.go b/integration_test.go
index f62e072..7dd6b24 100644
--- a/integration_test.go
+++ b/integration_test.go
@@ -66,6 +66,7 @@
 			runGo("Build", workDir, "go", "build", "./...")
 			runGo("TestNormal", workDir, "go", "test", "-race", "./...")
 			runGo("TestPureGo", workDir, "go", "test", "-race", "-tags", "purego", "./...")
+			runGo("TestReflect", workDir, "go", "test", "-race", "-tags", "protoreflect", "./...")
 			if v == golangLatest {
 				runGo("TestProto1Legacy", workDir, "go", "test", "-race", "-tags", "proto1_legacy", "./...")
 				runGo("TestProtocGenGo", "cmd/protoc-gen-go/testdata", "go", "test")
diff --git a/proto/decode.go b/proto/decode.go
index 11fed46..3e00074 100644
--- a/proto/decode.go
+++ b/proto/decode.go
@@ -25,10 +25,6 @@
 	// If DiscardUnknown is set, unknown fields are ignored.
 	DiscardUnknown bool
 
-	// Reflection forces use of the reflection-based decoder, even for
-	// messages which implement fast-path deserialization.
-	Reflection bool
-
 	pragma.NoUnkeyedLiterals
 }
 
@@ -57,9 +53,6 @@
 }
 
 func (o UnmarshalOptions) unmarshalMessageFast(b []byte, m Message) error {
-	if o.Reflection {
-		return errInternalNoFast
-	}
 	methods := protoMethods(m)
 	if methods == nil || methods.Unmarshal == nil {
 		return errInternalNoFast
diff --git a/proto/encode.go b/proto/encode.go
index fc3ce92..1626c3f 100644
--- a/proto/encode.go
+++ b/proto/encode.go
@@ -47,10 +47,6 @@
 	// detail and subject to change.
 	Deterministic bool
 
-	// Reflection forces use of the reflection-based encoder, even for
-	// messages which implement fast-path serialization.
-	Reflection bool
-
 	pragma.NoUnkeyedLiterals
 }
 
@@ -84,9 +80,6 @@
 }
 
 func (o MarshalOptions) marshalMessageFast(b []byte, m Message) ([]byte, error) {
-	if o.Reflection {
-		return nil, errInternalNoFast
-	}
 	methods := protoMethods(m)
 	if methods == nil ||
 		methods.MarshalAppend == nil ||
diff --git a/proto/proto.go b/proto/proto.go
index 96dac1c..da2a22c 100644
--- a/proto/proto.go
+++ b/proto/proto.go
@@ -7,7 +7,6 @@
 import (
 	"github.com/golang/protobuf/v2/internal/errors"
 	"github.com/golang/protobuf/v2/reflect/protoreflect"
-	"github.com/golang/protobuf/v2/runtime/protoiface"
 )
 
 // Message is the top-level interface that all messages must implement.
@@ -15,10 +14,3 @@
 
 // errInternalNoFast indicates that fast-path operations are not available for a message.
 var errInternalNoFast = errors.New("BUG: internal error (errInternalNoFast)")
-
-func protoMethods(m Message) *protoiface.Methods {
-	if x, ok := m.(protoiface.Methoder); ok {
-		return x.XXX_Methods()
-	}
-	return nil
-}
diff --git a/proto/proto_methods.go b/proto/proto_methods.go
new file mode 100644
index 0000000..360a1ee
--- /dev/null
+++ b/proto/proto_methods.go
@@ -0,0 +1,17 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The protoreflect build tag disables use of fast-path methods.
+// +build !protoreflect
+
+package proto
+
+import "github.com/golang/protobuf/v2/runtime/protoiface"
+
+func protoMethods(m Message) *protoiface.Methods {
+	if x, ok := m.(protoiface.Methoder); ok {
+		return x.XXX_Methods()
+	}
+	return nil
+}
diff --git a/proto/proto_reflect.go b/proto/proto_reflect.go
new file mode 100644
index 0000000..b282f3c
--- /dev/null
+++ b/proto/proto_reflect.go
@@ -0,0 +1,14 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The protoreflect build tag disables use of fast-path methods.
+// +build protoreflect
+
+package proto
+
+import "github.com/golang/protobuf/v2/runtime/protoiface"
+
+func protoMethods(m Message) *protoiface.Methods {
+	return nil
+}
diff --git a/runtime/protoiface/methods.go b/runtime/protoiface/methods.go
index dda5e49..e7d92db 100644
--- a/runtime/protoiface/methods.go
+++ b/runtime/protoiface/methods.go
@@ -55,7 +55,6 @@
 type MarshalOptions struct {
 	AllowPartial  bool
 	Deterministic bool
-	Reflection    bool
 
 	pragma.NoUnkeyedLiterals
 }
@@ -66,7 +65,6 @@
 type UnmarshalOptions struct {
 	AllowPartial   bool
 	DiscardUnknown bool
-	Reflection     bool
 
 	pragma.NoUnkeyedLiterals
 }