-
Notifications
You must be signed in to change notification settings - Fork 16.1k
Description
What language does this apply to?
If it's a proto syntax change, is it for proto2 or proto3?
If it's about generated code change, what programming language?
Ruby
Describe the problem you are trying to solve.
In this change the AbstractMessage parent class was added for Ruby code. The motivation was to be a pure performance win, exploiting how classes and objects are laid out in the Ruby code.
But as it happens, having a common base class that has all these methods defined is particularly convenient. When using an optional static type checker in a Ruby project, it's very easy if you can write Google::Protobuf::AbstractMessage in a type signature, and know that it has all these methods. For example, using Sorbet, it would be possible to write a signature like
sig do
params(
proto_class: T.class_of(Google::Protobuf::AbstractMessage),
bytes: String
)
.returns(Google::Protobuf::AbstractMessage)
end
def decode_and_log(proto_class, bytes)
puts("Decoding with class: #{proto_class.descriptor.name}")
proto_class.decode(bytes)
endRight now it's annoying to write signatures for these methods, because methods like descriptor and decode aren't actually defined on the only other common type in the inheritance hierarchy, MessageExts::ClassMethods:
[dev] main:0> Google::Protobuf::MessageExts::ClassMethods.instance_methods
=> []
So there's not a convenient type you can write—but there would be if AbstractMessage were not a private constant.
Describe the solution you'd like
Can we remove private_constant :AbstractMessage?
| private_constant :AbstractMessage |
Describe alternatives you've considered
An alternative would be to actually define the methods on MessageExts::ClassMethods.
In the Sorbet type system this is slightly less ergonomic to use, MessageExts and MessageExts::ClassMethods look like completely orthogonal modules to the type system. (For example, it doesn't know that MessageExts::ClassMethods has all the methods that a normal class would have, like .name or .ancestors.) That means you have to go around writing things like T.all(Google::Protobuf::MessageExts, Class) which is confusing.
It's a lot easier to just mention the exact superclass you want in your type annotation, which in this case is AbstractMessage.
Additional context
Add any other context or screenshots about the feature request here.