Clarify same-crate-import vs different-crate-import message fields (latter unsupported).

PiperOrigin-RevId: 579175657
pull/14613/head
Protobuf Team Bot 1 year ago committed by Copybara-Service
parent 4721f6a5e9
commit 6ee7a322d3
  1. 15
      src/google/protobuf/compiler/rust/accessors/accessors.cc
  2. 9
      src/google/protobuf/compiler/rust/accessors/singular_message.cc
  3. 43
      src/google/protobuf/compiler/rust/context.h
  4. 23
      src/google/protobuf/compiler/rust/generator.cc

@ -23,7 +23,8 @@ namespace rust {
namespace { namespace {
std::unique_ptr<AccessorGenerator> AccessorGeneratorFor( std::unique_ptr<AccessorGenerator> AccessorGeneratorFor(
const FieldDescriptor& desc) { Context<FieldDescriptor> field) {
const FieldDescriptor& desc = field.desc();
// TODO: We do not support [ctype=FOO] (used to set the field // TODO: We do not support [ctype=FOO] (used to set the field
// type in C++ to cord or string_piece) in V0.6 API. // type in C++ to cord or string_piece) in V0.6 API.
if (desc.options().has_ctype()) { if (desc.options().has_ctype()) {
@ -59,6 +60,12 @@ std::unique_ptr<AccessorGenerator> AccessorGeneratorFor(
if (desc.is_repeated()) { if (desc.is_repeated()) {
return std::make_unique<UnsupportedField>("repeated msg not supported"); return std::make_unique<UnsupportedField>("repeated msg not supported");
} }
if (!field.generator_context().is_file_in_current_crate(
desc.message_type()->file())) {
return std::make_unique<UnsupportedField>(
"message fields that are imported from another proto_library"
" (defined in a separate Rust crate) are not supported");
}
return std::make_unique<SingularMessage>(); return std::make_unique<SingularMessage>();
case FieldDescriptor::TYPE_ENUM: case FieldDescriptor::TYPE_ENUM:
@ -74,15 +81,15 @@ std::unique_ptr<AccessorGenerator> AccessorGeneratorFor(
} // namespace } // namespace
void GenerateAccessorMsgImpl(Context<FieldDescriptor> field) { void GenerateAccessorMsgImpl(Context<FieldDescriptor> field) {
AccessorGeneratorFor(field.desc())->GenerateMsgImpl(field); AccessorGeneratorFor(field)->GenerateMsgImpl(field);
} }
void GenerateAccessorExternC(Context<FieldDescriptor> field) { void GenerateAccessorExternC(Context<FieldDescriptor> field) {
AccessorGeneratorFor(field.desc())->GenerateExternC(field); AccessorGeneratorFor(field)->GenerateExternC(field);
} }
void GenerateAccessorThunkCc(Context<FieldDescriptor> field) { void GenerateAccessorThunkCc(Context<FieldDescriptor> field) {
AccessorGeneratorFor(field.desc())->GenerateThunkCc(field); AccessorGeneratorFor(field)->GenerateThunkCc(field);
} }
} // namespace rust } // namespace rust

@ -5,7 +5,6 @@
// license that can be found in the LICENSE file or at // license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd // https://developers.google.com/open-source/licenses/bsd
#include "absl/strings/match.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/cpp/helpers.h"
#include "google/protobuf/compiler/rust/accessors/accessor_generator.h" #include "google/protobuf/compiler/rust/accessors/accessor_generator.h"
@ -20,13 +19,9 @@ namespace rust {
void SingularMessage::InMsgImpl(Context<FieldDescriptor> field) const { void SingularMessage::InMsgImpl(Context<FieldDescriptor> field) const {
Context<Descriptor> d = field.WithDesc(field.desc().message_type()); Context<Descriptor> d = field.WithDesc(field.desc().message_type());
auto prefix = "crate::" + GetCrateRelativeQualifiedPath(d); auto prefix = "crate::" + GetCrateRelativeQualifiedPath(d);
// here we defer unit tests with messages that have import inside their
// pkg name e.g. unittest_import.proto
if (absl::StrContains(prefix, "import")) {
// TODO: Handle imports correctly, default to $Msg$View for now
prefix = field.desc().containing_type()->name();
}
if (field.is_cpp()) { if (field.is_cpp()) {
field.Emit({{"prefix", prefix}, field.Emit({{"prefix", prefix},
{"field", field.desc().name()}, {"field", field.desc().name()},

@ -8,10 +8,14 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_RUST_CONTEXT_H__ #ifndef GOOGLE_PROTOBUF_COMPILER_RUST_CONTEXT_H__
#define GOOGLE_PROTOBUF_COMPILER_RUST_CONTEXT_H__ #define GOOGLE_PROTOBUF_COMPILER_RUST_CONTEXT_H__
#include <algorithm>
#include <vector>
#include "absl/log/absl_log.h" #include "absl/log/absl_log.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "absl/types/span.h" #include "absl/types/span.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/io/printer.h" #include "google/protobuf/io/printer.h"
namespace google { namespace google {
@ -43,6 +47,26 @@ struct Options {
static absl::StatusOr<Options> Parse(absl::string_view param); static absl::StatusOr<Options> Parse(absl::string_view param);
}; };
class RustGeneratorContext {
public:
explicit RustGeneratorContext(
const std::vector<const FileDescriptor*>* files_in_current_crate)
: files_in_current_crate_(*files_in_current_crate) {}
const FileDescriptor* primary_file() const {
return files_in_current_crate_.front();
}
bool is_file_in_current_crate(const FileDescriptor* f) const {
return std::find(files_in_current_crate_.begin(),
files_in_current_crate_.end(),
f) != files_in_current_crate_.end();
}
private:
const std::vector<const FileDescriptor*>& files_in_current_crate_;
};
// A context for generating a particular kind of definition. // A context for generating a particular kind of definition.
// This type acts as an options struct (as in go/totw/173) for most of the // This type acts as an options struct (as in go/totw/173) for most of the
// generator. // generator.
@ -52,14 +76,22 @@ struct Options {
template <typename Descriptor> template <typename Descriptor>
class Context { class Context {
public: public:
Context(const Options* opts, const Descriptor* desc, io::Printer* printer) Context(const Options* opts, const Descriptor* desc,
: opts_(opts), desc_(desc), printer_(printer) {} const RustGeneratorContext* rust_generator_context,
io::Printer* printer)
: opts_(opts),
desc_(desc),
rust_generator_context_(rust_generator_context),
printer_(printer) {}
Context(const Context&) = default; Context(const Context&) = default;
Context& operator=(const Context&) = default; Context& operator=(const Context&) = default;
const Descriptor& desc() const { return *desc_; } const Descriptor& desc() const { return *desc_; }
const Options& opts() const { return *opts_; } const Options& opts() const { return *opts_; }
const RustGeneratorContext& generator_context() const {
return *rust_generator_context_;
}
bool is_cpp() const { return opts_->kernel == Kernel::kCpp; } bool is_cpp() const { return opts_->kernel == Kernel::kCpp; }
bool is_upb() const { return opts_->kernel == Kernel::kUpb; } bool is_upb() const { return opts_->kernel == Kernel::kUpb; }
@ -70,16 +102,16 @@ class Context {
// Creates a new context over a different descriptor. // Creates a new context over a different descriptor.
template <typename D> template <typename D>
Context<D> WithDesc(const D& desc) const { Context<D> WithDesc(const D& desc) const {
return Context<D>(opts_, &desc, printer_); return Context<D>(opts_, &desc, rust_generator_context_, printer_);
} }
template <typename D> template <typename D>
Context<D> WithDesc(const D* desc) const { Context<D> WithDesc(const D* desc) const {
return Context<D>(opts_, desc, printer_); return Context<D>(opts_, desc, rust_generator_context_, printer_);
} }
Context WithPrinter(io::Printer* printer) const { Context WithPrinter(io::Printer* printer) const {
return Context(opts_, desc_, printer); return Context(opts_, desc_, rust_generator_context_, printer);
} }
// Forwards to Emit(), which will likely be called all the time. // Forwards to Emit(), which will likely be called all the time.
@ -97,6 +129,7 @@ class Context {
private: private:
const Options* opts_; const Options* opts_;
const Descriptor* desc_; const Descriptor* desc_;
const RustGeneratorContext* rust_generator_context_;
io::Printer* printer_; io::Printer* printer_;
}; };
} // namespace rust } // namespace rust

@ -123,11 +123,7 @@ void EmitPubUseForImportedMessages(Context<FileDescriptor>& primary_file,
} }
// Emits all public imports of the current file // Emits all public imports of the current file
void EmitPublicImports( void EmitPublicImports(Context<FileDescriptor>& primary_file) {
Context<FileDescriptor>& primary_file,
const std::vector<const FileDescriptor*>& files_in_current_crate) {
absl::flat_hash_set<const FileDescriptor*> files(
files_in_current_crate.begin(), files_in_current_crate.end());
for (int i = 0; i < primary_file.desc().public_dependency_count(); ++i) { for (int i = 0; i < primary_file.desc().public_dependency_count(); ++i) {
auto dep_file = primary_file.desc().public_dependency(i); auto dep_file = primary_file.desc().public_dependency(i);
// If the publicly imported file is a src of the current `proto_library` // If the publicly imported file is a src of the current `proto_library`
@ -137,7 +133,8 @@ void EmitPublicImports(
// TODO: Handle the case where a non-primary src with the same // TODO: Handle the case where a non-primary src with the same
// declared package as the primary src publicly imports a file that the // declared package as the primary src publicly imports a file that the
// primary doesn't. // primary doesn't.
if (files.contains(dep_file)) continue; if (primary_file.generator_context().is_file_in_current_crate(dep_file))
continue;
auto dep = primary_file.WithDesc(dep_file); auto dep = primary_file.WithDesc(dep_file);
EmitPubUseForImportedMessages(primary_file, dep); EmitPubUseForImportedMessages(primary_file, dep);
} }
@ -206,7 +203,13 @@ bool RustGenerator::Generate(const FileDescriptor* file_desc,
return false; return false;
} }
Context<FileDescriptor> file(&*opts, file_desc, nullptr); std::vector<const FileDescriptor*> files_in_current_crate;
generator_context->ListParsedFiles(&files_in_current_crate);
RustGeneratorContext rust_generator_context(&files_in_current_crate);
Context<FileDescriptor> file(&*opts, file_desc, &rust_generator_context,
nullptr);
auto outfile = absl::WrapUnique(generator_context->Open(GetRsFile(file))); auto outfile = absl::WrapUnique(generator_context->Open(GetRsFile(file)));
io::Printer printer(outfile.get()); io::Printer printer(outfile.get());
@ -228,15 +231,13 @@ bool RustGenerator::Generate(const FileDescriptor* file_desc,
)rs"); )rs");
std::vector<const FileDescriptor*> files_in_current_crate;
generator_context->ListParsedFiles(&files_in_current_crate);
std::vector<Context<FileDescriptor>> file_contexts; std::vector<Context<FileDescriptor>> file_contexts;
for (const FileDescriptor* f : files_in_current_crate) { for (const FileDescriptor* f : files_in_current_crate) {
file_contexts.push_back(file.WithDesc(*f)); file_contexts.push_back(file.WithDesc(*f));
} }
// Generating the primary file? // Generating the primary file?
if (file_desc == files_in_current_crate.front()) { if (file_desc == rust_generator_context.primary_file()) {
auto non_primary_srcs = absl::MakeConstSpan(file_contexts).subspan(1); auto non_primary_srcs = absl::MakeConstSpan(file_contexts).subspan(1);
DeclareSubmodulesForNonPrimarySrcs(file, non_primary_srcs); DeclareSubmodulesForNonPrimarySrcs(file, non_primary_srcs);
@ -252,7 +253,7 @@ bool RustGenerator::Generate(const FileDescriptor* file_desc,
} }
} }
EmitPublicImports(file, files_in_current_crate); EmitPublicImports(file);
std::unique_ptr<io::ZeroCopyOutputStream> thunks_cc; std::unique_ptr<io::ZeroCopyOutputStream> thunks_cc;
std::unique_ptr<io::Printer> thunks_printer; std::unique_ptr<io::Printer> thunks_printer;

Loading…
Cancel
Save