diff --git a/src/google/protobuf/compiler/rust/accessors/accessors.cc b/src/google/protobuf/compiler/rust/accessors/accessors.cc index e963e9e075..f3664229ca 100644 --- a/src/google/protobuf/compiler/rust/accessors/accessors.cc +++ b/src/google/protobuf/compiler/rust/accessors/accessors.cc @@ -23,7 +23,8 @@ namespace rust { namespace { std::unique_ptr AccessorGeneratorFor( - const FieldDescriptor& desc) { + Context field) { + const FieldDescriptor& desc = field.desc(); // TODO: We do not support [ctype=FOO] (used to set the field // type in C++ to cord or string_piece) in V0.6 API. if (desc.options().has_ctype()) { @@ -59,6 +60,12 @@ std::unique_ptr AccessorGeneratorFor( if (desc.is_repeated()) { return std::make_unique("repeated msg not supported"); } + if (!field.generator_context().is_file_in_current_crate( + desc.message_type()->file())) { + return std::make_unique( + "message fields that are imported from another proto_library" + " (defined in a separate Rust crate) are not supported"); + } return std::make_unique(); case FieldDescriptor::TYPE_ENUM: @@ -74,15 +81,15 @@ std::unique_ptr AccessorGeneratorFor( } // namespace void GenerateAccessorMsgImpl(Context field) { - AccessorGeneratorFor(field.desc())->GenerateMsgImpl(field); + AccessorGeneratorFor(field)->GenerateMsgImpl(field); } void GenerateAccessorExternC(Context field) { - AccessorGeneratorFor(field.desc())->GenerateExternC(field); + AccessorGeneratorFor(field)->GenerateExternC(field); } void GenerateAccessorThunkCc(Context field) { - AccessorGeneratorFor(field.desc())->GenerateThunkCc(field); + AccessorGeneratorFor(field)->GenerateThunkCc(field); } } // namespace rust diff --git a/src/google/protobuf/compiler/rust/accessors/singular_message.cc b/src/google/protobuf/compiler/rust/accessors/singular_message.cc index 2978631faf..26f3358b75 100644 --- a/src/google/protobuf/compiler/rust/accessors/singular_message.cc +++ b/src/google/protobuf/compiler/rust/accessors/singular_message.cc @@ -5,7 +5,6 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "absl/strings/match.h" #include "absl/strings/string_view.h" #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/rust/accessors/accessor_generator.h" @@ -20,13 +19,9 @@ namespace rust { void SingularMessage::InMsgImpl(Context field) const { Context d = field.WithDesc(field.desc().message_type()); + 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()) { field.Emit({{"prefix", prefix}, {"field", field.desc().name()}, diff --git a/src/google/protobuf/compiler/rust/context.h b/src/google/protobuf/compiler/rust/context.h index 1158fbd795..ac31e99d68 100644 --- a/src/google/protobuf/compiler/rust/context.h +++ b/src/google/protobuf/compiler/rust/context.h @@ -8,10 +8,14 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_RUST_CONTEXT_H__ #define GOOGLE_PROTOBUF_COMPILER_RUST_CONTEXT_H__ +#include +#include + #include "absl/log/absl_log.h" #include "absl/status/statusor.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" +#include "google/protobuf/descriptor.h" #include "google/protobuf/io/printer.h" namespace google { @@ -43,6 +47,26 @@ struct Options { static absl::StatusOr Parse(absl::string_view param); }; +class RustGeneratorContext { + public: + explicit RustGeneratorContext( + const std::vector* 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& files_in_current_crate_; +}; + // 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 // generator. @@ -52,14 +76,22 @@ struct Options { template class Context { public: - Context(const Options* opts, const Descriptor* desc, io::Printer* printer) - : opts_(opts), desc_(desc), printer_(printer) {} + Context(const Options* opts, const Descriptor* desc, + 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& operator=(const Context&) = default; const Descriptor& desc() const { return *desc_; } 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_upb() const { return opts_->kernel == Kernel::kUpb; } @@ -70,16 +102,16 @@ class Context { // Creates a new context over a different descriptor. template Context WithDesc(const D& desc) const { - return Context(opts_, &desc, printer_); + return Context(opts_, &desc, rust_generator_context_, printer_); } template Context WithDesc(const D* desc) const { - return Context(opts_, desc, printer_); + return Context(opts_, desc, rust_generator_context_, printer_); } 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. @@ -97,6 +129,7 @@ class Context { private: const Options* opts_; const Descriptor* desc_; + const RustGeneratorContext* rust_generator_context_; io::Printer* printer_; }; } // namespace rust diff --git a/src/google/protobuf/compiler/rust/generator.cc b/src/google/protobuf/compiler/rust/generator.cc index 4027376102..585b7aae83 100644 --- a/src/google/protobuf/compiler/rust/generator.cc +++ b/src/google/protobuf/compiler/rust/generator.cc @@ -123,11 +123,7 @@ void EmitPubUseForImportedMessages(Context& primary_file, } // Emits all public imports of the current file -void EmitPublicImports( - Context& primary_file, - const std::vector& files_in_current_crate) { - absl::flat_hash_set files( - files_in_current_crate.begin(), files_in_current_crate.end()); +void EmitPublicImports(Context& primary_file) { for (int i = 0; i < primary_file.desc().public_dependency_count(); ++i) { auto dep_file = primary_file.desc().public_dependency(i); // 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 // declared package as the primary src publicly imports a file that the // 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); EmitPubUseForImportedMessages(primary_file, dep); } @@ -206,7 +203,13 @@ bool RustGenerator::Generate(const FileDescriptor* file_desc, return false; } - Context file(&*opts, file_desc, nullptr); + std::vector files_in_current_crate; + generator_context->ListParsedFiles(&files_in_current_crate); + + RustGeneratorContext rust_generator_context(&files_in_current_crate); + + Context file(&*opts, file_desc, &rust_generator_context, + nullptr); auto outfile = absl::WrapUnique(generator_context->Open(GetRsFile(file))); io::Printer printer(outfile.get()); @@ -228,15 +231,13 @@ bool RustGenerator::Generate(const FileDescriptor* file_desc, )rs"); - std::vector files_in_current_crate; - generator_context->ListParsedFiles(&files_in_current_crate); std::vector> file_contexts; for (const FileDescriptor* f : files_in_current_crate) { file_contexts.push_back(file.WithDesc(*f)); } // 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); 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 thunks_cc; std::unique_ptr thunks_printer;