diff --git a/cmd/protoc-gen-go/internal_gengo/main.go b/cmd/protoc-gen-go/internal_gengo/main.go
index 69e4aecaf..40e5f0508 100644
--- a/cmd/protoc-gen-go/internal_gengo/main.go
+++ b/cmd/protoc-gen-go/internal_gengo/main.go
@@ -17,6 +17,7 @@ import (
 	"unicode/utf8"
 
 	"google.golang.org/protobuf/compiler/protogen"
+	"google.golang.org/protobuf/internal/editionssupport"
 	"google.golang.org/protobuf/internal/encoding/tag"
 	"google.golang.org/protobuf/internal/filedesc"
 	"google.golang.org/protobuf/internal/genid"
@@ -29,7 +30,10 @@ import (
 )
 
 // SupportedFeatures reports the set of supported protobuf language features.
-var SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)
+var SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL | pluginpb.CodeGeneratorResponse_FEATURE_SUPPORTS_EDITIONS)
+
+var SupportedEditionsMinimum = editionssupport.Minimum
+var SupportedEditionsMaximum = editionssupport.Maximum
 
 // GenerateVersionMarkers specifies whether to generate version markers.
 var GenerateVersionMarkers = true
diff --git a/compiler/protogen/protogen.go b/compiler/protogen/protogen.go
index 914c57b1b..7a43a011a 100644
--- a/compiler/protogen/protogen.go
+++ b/compiler/protogen/protogen.go
@@ -108,6 +108,9 @@ type Plugin struct {
 	// google.protobuf.CodeGeneratorResponse.supported_features for details.
 	SupportedFeatures uint64
 
+	SupportedEditionsMinimum descriptorpb.Edition
+	SupportedEditionsMaximum descriptorpb.Edition
+
 	fileReg        *protoregistry.Files
 	enumsByName    map[protoreflect.FullName]*Enum
 	messagesByName map[protoreflect.FullName]*Message
@@ -396,6 +399,10 @@ func (gen *Plugin) Response() *pluginpb.CodeGeneratorResponse {
 	if gen.SupportedFeatures > 0 {
 		resp.SupportedFeatures = proto.Uint64(gen.SupportedFeatures)
 	}
+	if gen.SupportedEditionsMinimum != descriptorpb.Edition_EDITION_UNKNOWN && gen.SupportedEditionsMaximum != descriptorpb.Edition_EDITION_UNKNOWN {
+		resp.MinimumEdition = proto.Int32(int32(gen.SupportedEditionsMinimum))
+		resp.MaximumEdition = proto.Int32(int32(gen.SupportedEditionsMaximum))
+	}
 	return resp
 }
 
diff --git a/internal/cmd/generate-protos/main.go b/internal/cmd/generate-protos/main.go
index b8720d7ff..14bfc23e4 100644
--- a/internal/cmd/generate-protos/main.go
+++ b/internal/cmd/generate-protos/main.go
@@ -24,7 +24,7 @@ import (
 	gengo "google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo"
 	"google.golang.org/protobuf/compiler/protogen"
 	"google.golang.org/protobuf/internal/detrand"
-	"google.golang.org/protobuf/reflect/protodesc"
+	"google.golang.org/protobuf/internal/editionssupport"
 )
 
 func init() {
@@ -108,8 +108,8 @@ func generateEditionsDefaults() {
 	// The enum in Go string formats to "EDITION_${EDITION}" but protoc expects
 	// the flag in the form "${EDITION}". To work around this, we trim the
 	// "EDITION_" prefix.
-	minEdition := strings.TrimPrefix(fmt.Sprint(protodesc.SupportedEditionsMinimum), "EDITION_")
-	maxEdition := strings.TrimPrefix(fmt.Sprint(protodesc.SupportedEditionsMaximum), "EDITION_")
+	minEdition := strings.TrimPrefix(fmt.Sprint(editionssupport.Minimum), "EDITION_")
+	maxEdition := strings.TrimPrefix(fmt.Sprint(editionssupport.Maximum), "EDITION_")
 	cmd := exec.Command(
 		"protoc",
 		"--experimental_edition_defaults_out", dest,
diff --git a/internal/editionssupport/editions.go b/internal/editionssupport/editions.go
new file mode 100644
index 000000000..029a6a12d
--- /dev/null
+++ b/internal/editionssupport/editions.go
@@ -0,0 +1,13 @@
+// Copyright 2024 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.
+
+// Package editionssupport defines constants for editions that are supported.
+package editionssupport
+
+import descriptorpb "google.golang.org/protobuf/types/descriptorpb"
+
+const (
+	Minimum = descriptorpb.Edition_EDITION_PROTO2
+	Maximum = descriptorpb.Edition_EDITION_2023
+)
diff --git a/internal/filedesc/desc.go b/internal/filedesc/desc.go
index 54122e0c3..903e9cd40 100644
--- a/internal/filedesc/desc.go
+++ b/internal/filedesc/desc.go
@@ -333,8 +333,7 @@ func (fd *Field) HasPresence() bool {
 	if fd.L1.Cardinality == protoreflect.Repeated {
 		return false
 	}
-	explicitFieldPresence := fd.Syntax() == protoreflect.Editions && fd.L1.EditionFeatures.IsFieldPresence
-	return fd.Syntax() == protoreflect.Proto2 || explicitFieldPresence || fd.L1.Message != nil || fd.L1.ContainingOneof != nil
+	return fd.L1.EditionFeatures.IsFieldPresence || fd.L1.Message != nil || fd.L1.ContainingOneof != nil
 }
 func (fd *Field) HasOptionalKeyword() bool {
 	return (fd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && fd.L1.Cardinality == protoreflect.Optional && fd.L1.ContainingOneof == nil) || fd.L1.IsProto3Optional
diff --git a/reflect/protodesc/desc.go b/reflect/protodesc/desc.go
index 6813d6b83..8fbecb4f5 100644
--- a/reflect/protodesc/desc.go
+++ b/reflect/protodesc/desc.go
@@ -13,6 +13,7 @@
 package protodesc
 
 import (
+	"google.golang.org/protobuf/internal/editionssupport"
 	"google.golang.org/protobuf/internal/errors"
 	"google.golang.org/protobuf/internal/filedesc"
 	"google.golang.org/protobuf/internal/pragma"
@@ -101,7 +102,7 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot
 	default:
 		return nil, errors.New("invalid syntax: %q", fd.GetSyntax())
 	}
-	if f.L1.Syntax == protoreflect.Editions && (fd.GetEdition() < SupportedEditionsMinimum || fd.GetEdition() > SupportedEditionsMaximum) {
+	if f.L1.Syntax == protoreflect.Editions && (fd.GetEdition() < editionssupport.Minimum || fd.GetEdition() > editionssupport.Maximum) {
 		return nil, errors.New("use of edition %v not yet supported by the Go Protobuf runtime", fd.GetEdition())
 	}
 	f.L1.Path = fd.GetName()
diff --git a/reflect/protodesc/editions.go b/reflect/protodesc/editions.go
index 2a6b29d17..f6a1fec6e 100644
--- a/reflect/protodesc/editions.go
+++ b/reflect/protodesc/editions.go
@@ -17,11 +17,6 @@ import (
 	gofeaturespb "google.golang.org/protobuf/types/gofeaturespb"
 )
 
-const (
-	SupportedEditionsMinimum = descriptorpb.Edition_EDITION_PROTO2
-	SupportedEditionsMaximum = descriptorpb.Edition_EDITION_2023
-)
-
 var defaults = &descriptorpb.FeatureSetDefaults{}
 var defaultsCacheMu sync.Mutex
 var defaultsCache = make(map[filedesc.Edition]*descriptorpb.FeatureSet)