Skip to content

Commit 3d5b665

Browse files
authored
Merge pull request #1149 from block/myron/steep-2.0.0
Upgrade steep/RBS to 2.0/4.0. Steep 2.0 + RBS 4.0 are stricter about: void in union types, duplicated method definitions across RBS files, missing interface method implementations. Most of these changes make our types more accurate.
1 parent a59afce commit 3d5b665

25 files changed

Lines changed: 91 additions & 45 deletions

File tree

AGENTS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ Custom gems can be added via `Gemfile-custom` (see `Gemfile-custom.example`), th
168168
### RBS Type Signatures
169169

170170
- When defining RBS signatures for extension modules, prefer declaring the concrete type a module extends rather than defining custom interfaces. For example, use `module IndexExtension : ::ElasticGraph::SchemaDefinition::Indexing::Index` instead of creating a custom `_IndexExtensionInterface`.
171+
- Place interface methods on the narrowest correct interface. If a method only exists on indexable types, put it on `_IndexableType`, not `_Type`.
172+
- Define `type` aliases (e.g. `type abstractType = InterfaceType | UnionType`) for repeated union types rather than duplicating them across signatures.
173+
- When Steep can't infer a narrowed type from an expression, prefer an inline RBS type annotation comment (e.g. `# : SchemaElements::InterfaceType`) over a `_ =` cast. Use `_ =` only as a last resort when an annotation won't work.
174+
- For `Data.define` blocks where Steep can't type-check the dynamically generated `initialize`, use `# @implements ClassName` with a corresponding `class ClassName < Data` in the RBS file that declares the method signatures. Avoid `__skip__ = def`.
175+
- Prefer `&:method_name` over explicit blocks. If Steep complains, add the missing method to the RBS rather than rewriting as `{ |x| x.method_name }`.
176+
- Keep `@ivar` declarations adjacent to their accessor method in the RBS, not grouped elsewhere.
177+
- Be precise about collection element types in RBS — e.g. if a `Set` only ever contains `UnionType`, type it as `Set[UnionType]` not `Set[UnionType | InterfaceType]`.
178+
- Use `@dynamic` annotations only for methods that actually exist at runtime (provided by delegation, Struct, or included modules). Never use `@dynamic` for methods that would raise `NoMethodError`.
171179

172180
### Testing
173181

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ group :development do
4040
gem "simplecov", "~> 0.22"
4141
gem "simplecov-console", "~> 0.9", ">= 0.9.5"
4242
gem "standard", "~> 1.54.0"
43-
gem "steep", "~> 1.10.0", platforms: :ruby
43+
gem "steep", "~> 2.0.0", platforms: :ruby
4444
gem "super_diff", "~> 0.18"
4545
gem "vcr", "~> 6.4"
4646
end

Gemfile.lock

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,6 @@ GEM
455455
multi_json (1.20.1)
456456
multi_json (1.20.1-java)
457457
concurrent-ruby (~> 1.2)
458-
mutex_m (0.3.0)
459458
net-http (0.9.1)
460459
uri (>= 0.11.1)
461460
nokogiri (1.19.2)
@@ -510,8 +509,9 @@ GEM
510509
rb-fsevent (0.11.2)
511510
rb-inotify (0.11.1)
512511
ffi (~> 1.0)
513-
rbs (3.10.4)
512+
rbs (4.0.2)
514513
logger
514+
prism (>= 1.6.0)
515515
tsort
516516
rdoc (7.2.0)
517517
erb
@@ -613,19 +613,18 @@ GEM
613613
standard-performance (1.9.0)
614614
lint_roller (~> 1.1)
615615
rubocop-performance (~> 1.26.0)
616-
steep (1.10.0)
617-
activesupport (>= 5.1)
616+
steep (2.0.0)
618617
concurrent-ruby (>= 1.1.10)
619618
csv (>= 3.0.9)
620619
fileutils (>= 1.1.0)
621620
json (>= 2.1.0)
622621
language_server-protocol (>= 3.17.0.4, < 4.0)
623622
listen (~> 3.0)
624623
logger (>= 1.3.0)
625-
mutex_m (>= 0.3.0)
626-
parser (>= 3.1)
624+
parser (>= 3.2)
625+
prism (>= 0.25.0)
627626
rainbow (>= 2.2.2, < 4.0)
628-
rbs (~> 3.9)
627+
rbs (~> 4.0)
629628
securerandom (>= 0.1)
630629
strscan (>= 1.0.0)
631630
terminal-table (>= 2, < 5)
@@ -733,7 +732,7 @@ DEPENDENCIES
733732
simplecov (~> 0.22)
734733
simplecov-console (~> 0.9, >= 0.9.5)
735734
standard (~> 1.54.0)
736-
steep (~> 1.10.0)
735+
steep (~> 2.0.0)
737736
super_diff (~> 0.18)
738737
vcr (~> 6.4)
739738
yard (~> 0.9, >= 0.9.43)
@@ -871,7 +870,6 @@ CHECKSUMS
871870
module_methods (0.1.0) sha256=71cabd8e5b8537316a2e4a543a778726f34fab048d6d5fe97f3766c7b4e406a1
872871
multi_json (1.20.1) sha256=2f3934e805cc45ef91b551a1f89d0e9191abd06a5e04a2ef09a6a036c452ca6d
873872
multi_json (1.20.1-java) sha256=db1b1e8a461ed0d024b30bfd462bab87e7ceedc967457ba3f791043fdf263b95
874-
mutex_m (0.3.0) sha256=cfcb04ac16b69c4813777022fdceda24e9f798e48092a2b817eb4c0a782b0751
875873
net-http (0.9.1) sha256=25ba0b67c63e89df626ed8fac771d0ad24ad151a858af2cc8e6a716ca4336996
876874
nokogiri (1.19.2) sha256=38fdd8b59db3d5ea9e7dfb14702e882b9bf819198d5bf976f17ebce12c481756
877875
nokogiri (1.19.2-arm-linux-gnu) sha256=b7fa1139016f3dc850bda1260988f0d749934a939d04ef2da13bec060d7d5081
@@ -900,7 +898,7 @@ CHECKSUMS
900898
rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
901899
rb-fsevent (0.11.2) sha256=43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe
902900
rb-inotify (0.11.1) sha256=a0a700441239b0ff18eb65e3866236cd78613d6b9f78fea1f9ac47a85e47be6e
903-
rbs (3.10.4) sha256=b17d7c4be4bb31a11a3b529830f0aa206a807ca42f2e7921a3027dfc6b7e5ce8
901+
rbs (4.0.2) sha256=af75671e66cd03434cc546622741ebf83f6197ec4328375805306330bf78ef25
904902
rdoc (7.2.0) sha256=8650f76cd4009c3b54955eb5d7e3a075c60a57276766ebf36f9085e8c9f23192
905903
redcarpet (3.6.1) sha256=d444910e6aa55480c6bcdc0cdb057626e8a32c054c29e793fa642ba2f155f445
906904
regexp_parser (2.12.0) sha256=35a916a1d63190ab5c9009457136ae5f3c0c7512d60291d0d1378ba18ce08ebb
@@ -942,7 +940,7 @@ CHECKSUMS
942940
standard (1.54.0) sha256=7a4b08f83d9893083c8f03bc486f0feeb6a84d48233b40829c03ef4767ea0100
943941
standard-custom (1.0.2) sha256=424adc84179a074f1a2a309bb9cf7cd6bfdb2b6541f20c6bf9436c0ba22a652b
944942
standard-performance (1.9.0) sha256=49483d31be448292951d80e5e67cdcb576c2502103c7b40aec6f1b6e9c88e3f2
945-
steep (1.10.0) sha256=1b295b55f9aaff1b8d3ee42453ee55bc2a1078fda0268f288edb2dc014f4d7d1
943+
steep (2.0.0) sha256=6eb0ecc09637bbb54f0a5f2cf63daea6d3208ccace64b4f1107d976333605c30
946944
stringio (3.2.0) sha256=c37cb2e58b4ffbd33fe5cd948c05934af997b36e0b6ca6fdf43afa234cf222e1
947945
strscan (3.1.8) sha256=aae2db611a225559f21ffbb71765c9a4e60fd262534a9ea84f4f11c7f32f679e
948946
strscan (3.1.8-java) sha256=07c9fb169931fc7327e9ae64b27999e355c2eadd0eaae4ed0f1e7d4e05a2b429

elasticgraph-apollo/lib/elastic_graph/apollo/schema_definition/api_extension.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ def define_apollo_schema_elements
345345
state.after_user_definition_complete do
346346
# Add @key directives to all root document types with an id field.
347347
state.object_types_by_name.values
348-
.grep(ElasticGraph::SchemaDefinition::SchemaElements::ObjectType)
348+
.grep(ElasticGraph::SchemaDefinition::SchemaElements::ObjectType) # : ::Array[::ElasticGraph::SchemaDefinition::SchemaElements::ObjectType & ObjectTypeExtension]
349349
.select { |object_type| object_type.root_document_type? && object_type.graphql_fields_by_name.key?("id") }
350350
.each { |object_type| object_type.apollo_key fields: "id" }
351351

elasticgraph-datastore_core/sig/elastic_graph/datastore_core/index_definition.rbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module ElasticGraph
88
def has_custom_routing?: () -> bool
99
def max_result_window: () -> ::Integer
1010
def searches_could_hit_incomplete_docs?: () -> bool
11-
def cluster_to_query: () -> ::String
11+
def cluster_to_query: () -> ::String?
1212
def clusters_to_index_into: () -> ::Array[::String]
1313
def ignored_values_for_routing: () -> ::Set[::String]
1414
def all_accessible_cluster_names: () -> ::Array[::String]

elasticgraph-health_check/lib/elastic_graph/health_check/health_checker.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ def validate_and_normalize_config(config)
225225
def all_known_clusters
226226
@all_known_clusters ||= @indexed_document_types_by_name.flat_map do |_, index_type|
227227
index_type.search_index_definitions.flat_map do |index_def|
228-
[index_def.cluster_to_query] + index_def.clusters_to_index_into
228+
[index_def.cluster_to_query].compact + index_def.clusters_to_index_into
229229
end
230230
end + @datastore_clients_by_name.keys
231231
end

elasticgraph-indexer/lib/elastic_graph/indexer/record_preparer.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,13 @@ def initialize(indexing_preparer_by_scalar_type_name, type_metas)
100100
def prepare_for_index(type_name, value, mapping_properties)
101101
type_name = type_name.delete_suffix("!")
102102

103-
return nil if value.nil?
103+
return (_ = nil) if value.nil? # Steep 2.0 narrows to nil here but can't see it satisfies T
104104

105105
if (preparer = @indexing_preparer_by_scalar_type_name[type_name])
106106
return (_ = preparer).prepare_for_indexing(value)
107107
end
108108

109-
case value
109+
_ = case value # Steep 2.0 can't narrow generic T through case/when branches
110110
when ::Array
111111
element_type_name = type_name.delete_prefix("[").delete_suffix("]")
112112
value.map { |v| prepare_for_index(element_type_name, v, mapping_properties) }

elasticgraph-indexer/sig/elastic_graph/indexer/record_preparer.rbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module ElasticGraph
22
class Indexer
33
interface _RecordPreparer
4-
def prepare_for_index: [T] (::String, T, ::Hash[::String, untyped]) -> T
4+
def prepare_for_index: [T < ::Object] (::String, T, ::Hash[::String, untyped]) -> T
55
end
66

77
class RecordPreparer

elasticgraph-local/sig/elastic_graph/local/rake_tasks.rbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ module ElasticGraph
3333
def define_docker_tasks: (::String, ::String, ::Array[::String], ::Regexp) -> void
3434
def define_docker_tasks_for_version: (::String, ::Symbol, ::String, port: ::Integer, version: ::String, env: ::String, ready_log_line: ::Regexp) -> void
3535
def define_other_tasks: () -> void
36+
def run_rackup: (::String) -> void
3637

3738
@local_datastore_url: ::String?
3839
def local_datastore_url: () -> ::String

elasticgraph-schema_definition/lib/elastic_graph/schema_definition/indexing/json_schema_with_metadata.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,13 @@ def identify_missing_necessary_fields(json_schema, old_type_name_by_current_name
158158

159159
@state.object_types_by_name.values
160160
.select { |type| type.has_own_index_def? && !@derived_indexing_type_names.include?(type.name) }
161-
.flat_map { |object_type| identify_missing_necessary_fields_for_index_def(object_type, object_type.own_index_def, json_schema_resolver, version) }
161+
.flat_map do |object_type|
162+
identify_missing_necessary_fields_for_index_def(
163+
object_type,
164+
object_type.own_index_def, # : Indexing::Index
165+
json_schema_resolver, version
166+
)
167+
end
162168
end
163169

164170
def identify_missing_necessary_fields_for_index_def(object_type, index_def, json_schema_resolver, json_schema_version)

0 commit comments

Comments
 (0)