steep 1.8.0.pre.1 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c87015f545300c9c126b0121aa9534db083c157fbd791b7117006b6683bdc05d
4
- data.tar.gz: 6bb606ac1b4cc9cdd6364745c02f878714cdf2ca2d61079376a3ea50fbf4b9ba
3
+ metadata.gz: 298dd973658fa586efbf59424298b54eb540a3e8f5b5c423f10ede9ae83d0d65
4
+ data.tar.gz: f9a21241e44c10744d3305111b9afe499855931acda999b8671a2276ade4b2d9
5
5
  SHA512:
6
- metadata.gz: 4787c76c6049f2e1a2a9856d26dd0157419a2f4258a185559d0fe676500380089d75b30f916e353836f0e6af4eab16e2d977a9be5798bcfae1d13f8902d21491
7
- data.tar.gz: 462bb7747747fd5a34bf3205cd71d94f22beb4efd4407e5e59fbc31c049583b8350cdac262591319ad2ed09d802d94e3ff42d2f9c54ba0addff5547c7258f898
6
+ metadata.gz: e110b36e04ba367ba26ce2f2a74b7aa6be20bb25df742af696803be795f7b372a92948f923c4b30548ad4c78657b0dcb19702a602721ef80136eb4f9d4e9daa1
7
+ data.tar.gz: 2a4e44c76e29539b8692e31aa5cdd3f438715b978ef5d4e264d26191f634ff3c0ff58488d0334816ca8e6e6b1ff0ce3d0a35140c51e1dea78d7e3b56a31a3fdd
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.8.0 (2024-09-30)
4
+
5
+ ### Type checker core
6
+
7
+ * RBS validation ([#1239](https://github.com/soutaro/steep/pull/1239))
8
+ * Add special path for `Kernel#class` method ([#1229](https://github.com/soutaro/steep/pull/1229))
9
+
10
+ ## 1.8.0.pre.2 (2024-09-18)
11
+
12
+ ### Type checker core
13
+
14
+ * Support non symbol record keys ([#1227](https://github.com/soutaro/steep/pull/1227))
15
+
3
16
  ## 1.8.0.pre.1 (2024-09-17)
4
17
 
5
18
  ### Type checker core
@@ -65,6 +65,7 @@ module Steep
65
65
  Regexp = Type.new("::Regexp")
66
66
  NilClass = Type.new("::NilClass")
67
67
  Proc = Type.new("::Proc")
68
+ Kernel = Type.new("::Kernel")
68
69
 
69
70
  def self.nil_type
70
71
  AST::Types::Nil.instance
@@ -27,7 +27,7 @@ module Steep
27
27
  end
28
28
 
29
29
  def to_s
30
- strings = elements.keys.sort.map do |key|
30
+ strings = elements.keys.sort_by(&:to_s).map do |key|
31
31
  if optional?(key)
32
32
  "?#{key.inspect} => #{elements[key]}"
33
33
  else
@@ -0,0 +1,48 @@
1
+ module Steep
2
+ module Diagnostic
3
+ module ResultPrinter2
4
+ def result_line(result)
5
+ case result
6
+ when Subtyping::Result::Failure
7
+ case result.error
8
+ when Subtyping::Result::Failure::UnknownPairError
9
+ nil
10
+ when Subtyping::Result::Failure::UnsatisfiedConstraints
11
+ "Unsatisfied constraints: #{result.relation}"
12
+ when Subtyping::Result::Failure::MethodMissingError
13
+ "Method `#{result.error.name}` is missing"
14
+ when Subtyping::Result::Failure::BlockMismatchError
15
+ "Incomaptible block: #{result.relation}"
16
+ when Subtyping::Result::Failure::ParameterMismatchError
17
+ if result.relation.params?
18
+ "Incompatible arity: #{result.relation.super_type} and #{result.relation.sub_type}"
19
+ else
20
+ "Incompatible arity: #{result.relation}"
21
+ end
22
+ when Subtyping::Result::Failure::PolyMethodSubtyping
23
+ "Unsupported polymorphic method comparison: #{result.relation}"
24
+ when Subtyping::Result::Failure::SelfBindingMismatch
25
+ "Incompatible block self type: #{result.relation}"
26
+ end
27
+ else
28
+ result.relation.to_s
29
+ end
30
+ end
31
+
32
+ def detail_lines
33
+ lines = StringIO.new.tap do |io|
34
+ failure_path = result.failure_path || []
35
+ failure_path.reverse_each.filter_map do |result|
36
+ result_line(result)
37
+ end.each.with_index(1) do |message, index|
38
+ io.puts "#{" " * (index)}#{message}"
39
+ end
40
+ end.string.chomp
41
+
42
+ unless lines.empty?
43
+ lines
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -61,51 +61,6 @@ module Steep
61
61
  end
62
62
  end
63
63
 
64
- module ResultPrinter2
65
- def result_line(result)
66
- case result
67
- when Subtyping::Result::Failure
68
- case result.error
69
- when Subtyping::Result::Failure::UnknownPairError
70
- nil
71
- when Subtyping::Result::Failure::UnsatisfiedConstraints
72
- "Unsatisfied constraints: #{result.relation}"
73
- when Subtyping::Result::Failure::MethodMissingError
74
- "Method `#{result.error.name}` is missing"
75
- when Subtyping::Result::Failure::BlockMismatchError
76
- "Incomaptible block: #{result.relation}"
77
- when Subtyping::Result::Failure::ParameterMismatchError
78
- if result.relation.params?
79
- "Incompatible arity: #{result.relation.super_type} and #{result.relation.sub_type}"
80
- else
81
- "Incompatible arity: #{result.relation}"
82
- end
83
- when Subtyping::Result::Failure::PolyMethodSubtyping
84
- "Unsupported polymorphic method comparison: #{result.relation}"
85
- when Subtyping::Result::Failure::SelfBindingMismatch
86
- "Incompatible block self type: #{result.relation}"
87
- end
88
- else
89
- result.relation.to_s
90
- end
91
- end
92
-
93
- def detail_lines
94
- lines = StringIO.new.tap do |io|
95
- failure_path = result.failure_path || []
96
- failure_path.reverse_each.filter_map do |result|
97
- result_line(result)
98
- end.each.with_index(1) do |message, index|
99
- io.puts "#{" " * (index)}#{message}"
100
- end
101
- end.string.chomp
102
-
103
- unless lines.empty?
104
- lines
105
- end
106
- end
107
- end
108
-
109
64
  class IncompatibleAssignment < Base
110
65
  attr_reader :lhs_type
111
66
  attr_reader :rhs_type
@@ -105,12 +105,16 @@ module Steep
105
105
  attr_reader :type_name
106
106
  attr_reader :type_arg
107
107
  attr_reader :type_param
108
+ attr_reader :result
108
109
 
109
- def initialize(type_name:, type_arg:, type_param:, location:)
110
+ include ResultPrinter2
111
+
112
+ def initialize(type_name:, type_arg:, type_param:, result:, location:)
110
113
  super(location: location)
111
114
  @type_name = type_name
112
115
  @type_arg = type_arg
113
116
  @type_param = type_param
117
+ @result = result
114
118
  end
115
119
 
116
120
  def header_line
@@ -248,14 +252,20 @@ module Steep
248
252
  class ModuleSelfTypeError < Base
249
253
  attr_reader :name
250
254
  attr_reader :ancestor
251
- attr_reader :relation
255
+ attr_reader :result
256
+
257
+ include ResultPrinter2
252
258
 
253
- def initialize(name:, ancestor:, relation:, location:)
259
+ def initialize(name:, ancestor:, result:, location:)
254
260
  super(location: location)
255
261
 
256
262
  @name = name
257
263
  @ancestor = ancestor
258
- @relation = relation
264
+ @result = result
265
+ end
266
+
267
+ def relation
268
+ result.relation
259
269
  end
260
270
 
261
271
  def header_line
@@ -417,6 +427,40 @@ module Steep
417
427
  end
418
428
  end
419
429
 
430
+ class TypeParamDefaultReferenceError < Base
431
+ attr_reader :type_param
432
+
433
+ def initialize(type_param, location:)
434
+ super(location: location)
435
+ @type_param = type_param
436
+ end
437
+
438
+ def header_line
439
+ "The default type of `#{type_param.name}` cannot depend on optional type parameters"
440
+ end
441
+ end
442
+
443
+ class UnsatisfiableGenericsDefaultType < Base
444
+ attr_reader :param_name, :result
445
+
446
+ include ResultPrinter2
447
+
448
+ def initialize(param_name, result, location:)
449
+ super(location: location)
450
+ @param_name = param_name
451
+ @result = result
452
+ end
453
+
454
+ def relation
455
+ result.relation
456
+ end
457
+
458
+ def header_line
459
+ "The default type of `#{param_name}` doesn't satisfy upper bound constarint: #{relation}"
460
+ end
461
+ end
462
+
463
+
420
464
  def self.from_rbs_error(error, factory:)
421
465
  case error
422
466
  when RBS::ParsingError
@@ -515,6 +559,8 @@ module Steep
515
559
  Diagnostic::Signature::InconsistentClassModuleAliasError.new(decl: error.alias_entry.decl)
516
560
  when RBS::CyclicClassAliasDefinitionError
517
561
  Diagnostic::Signature::CyclicClassAliasDefinitionError.new(decl: error.alias_entry.decl)
562
+ when RBS::TypeParamDefaultReferenceError
563
+ Diagnostic::Signature::TypeParamDefaultReferenceError.new(error.type_param, location: error.location)
518
564
  else
519
565
  raise error
520
566
  end
@@ -281,6 +281,7 @@ module Steep
281
281
  method_name = method_name_for(type_def, name)
282
282
  method_type = factory.method_type(type_def.type)
283
283
  method_type = replace_primitive_method(method_name, type_def, method_type)
284
+ method_type = replace_kernel_class(method_name, type_def, method_type) { AST::Builtin::Class.instance_type }
284
285
  Shape::MethodOverload.new(method_type, [type_def])
285
286
  end
286
287
 
@@ -311,6 +312,9 @@ module Steep
311
312
  method_name = method_name_for(type_def, name)
312
313
  method_type = factory.method_type(type_def.type)
313
314
  method_type = replace_primitive_method(method_name, type_def, method_type)
315
+ if type_name.class?
316
+ method_type = replace_kernel_class(method_name, type_def, method_type) { AST::Types::Name::Singleton.new(name: type_name) }
317
+ end
314
318
  Shape::MethodOverload.new(method_type, [type_def])
315
319
  end
316
320
 
@@ -748,7 +752,7 @@ module Steep
748
752
  return_type: AST::Types::Logic::ReceiverIsNil.instance()
749
753
  )
750
754
  )
751
- end
755
+ end
752
756
  end
753
757
 
754
758
  when :!
@@ -801,6 +805,23 @@ module Steep
801
805
 
802
806
  method_type
803
807
  end
808
+
809
+ def replace_kernel_class(method_name, method_def, method_type)
810
+ defined_in = method_def.defined_in
811
+ member = method_def.member
812
+
813
+ if member.is_a?(RBS::AST::Members::MethodDefinition)
814
+ case method_name.method_name
815
+ when :class
816
+ case defined_in
817
+ when AST::Builtin::Kernel.module_name
818
+ return method_type.with(type: method_type.type.with(return_type: yield))
819
+ end
820
+ end
821
+ end
822
+
823
+ method_type
824
+ end
804
825
  end
805
826
  end
806
827
  end
@@ -104,6 +104,7 @@ module Steep
104
104
  unchecked: param.unchecked?,
105
105
  default_type: factory.type_opt(param.default_type)
106
106
  ),
107
+ result: result,
107
108
  location: location
108
109
  )
109
110
  end
@@ -252,6 +253,39 @@ module Steep
252
253
  end
253
254
  end
254
255
 
256
+ def validate_type_params(type_name, type_params)
257
+ if error_type_params = RBS::AST::TypeParam.validate(type_params)
258
+ error_type_params.each do |type_param|
259
+ default_type = type_param.default_type or raise
260
+ @errors << Diagnostic::Signature::TypeParamDefaultReferenceError.new(type_param, location: default_type.location)
261
+ end
262
+ end
263
+
264
+ upper_bounds = type_params.each.with_object({}) do |param, bounds| #$ Hash[Symbol, AST::Types::t?]
265
+ bounds[param.name] = factory.type_opt(param.upper_bound_type)
266
+ end
267
+
268
+ checker.push_variable_bounds(upper_bounds) do
269
+ type_params.each do |type_param|
270
+ param = checker.factory.type_param(type_param)
271
+
272
+ default_type = param.default_type or next
273
+ upper_bound = param.upper_bound or next
274
+
275
+ relation = Subtyping::Relation.new(sub_type: default_type, super_type: upper_bound)
276
+ result = checker.check(relation, self_type: nil, instance_type: nil, class_type: nil, constraints: Subtyping::Constraints.empty)
277
+
278
+ if result.failure?
279
+ @errors << Diagnostic::Signature::UnsatisfiableGenericsDefaultType.new(
280
+ type_param.name,
281
+ result,
282
+ location: (type_param.default_type || raise).location
283
+ )
284
+ end
285
+ end
286
+ end
287
+ end
288
+
255
289
  def validate_one_class_decl(name, entry)
256
290
  rescue_validation_errors(name) do
257
291
  Steep.logger.debug { "Validating class definition `#{name}`..." }
@@ -310,7 +344,7 @@ module Steep
310
344
  name: name,
311
345
  location: ancestor.source&.location || raise,
312
346
  ancestor: ancestor,
313
- relation: relation
347
+ result: _1
314
348
  )
315
349
  end
316
350
  end
@@ -405,7 +439,7 @@ module Steep
405
439
  name: name,
406
440
  location: ancestor.source&.location || raise,
407
441
  ancestor: ancestor,
408
- relation: relation
442
+ result: _1
409
443
  )
410
444
  end
411
445
  end
@@ -419,6 +453,8 @@ module Steep
419
453
  validate_definition_type(definition)
420
454
  end
421
455
  end
456
+
457
+ validate_type_params(name, entry.type_params)
422
458
  end
423
459
  end
424
460
  end
@@ -480,6 +516,8 @@ module Steep
480
516
  Steep.logger.tagged "#{name}" do
481
517
  definition = builder.build_interface(name)
482
518
 
519
+ validate_type_params(name, definition.type_params_decl)
520
+
483
521
  upper_bounds = definition.type_params_decl.each.with_object({}) do |param, bounds|
484
522
  bounds[param.name] = factory.type_opt(param.upper_bound_type)
485
523
  end
@@ -575,6 +613,8 @@ module Steep
575
613
  builder.validate_type_name(outer, entry.decl.location&.aref(:name))
576
614
  end
577
615
 
616
+ validate_type_params(name, entry.decl.type_params)
617
+
578
618
  upper_bounds = entry.decl.type_params.each.with_object({}) do |param, bounds|
579
619
  bounds[param.name] = factory.type_opt(param.upper_bound_type)
580
620
  end
@@ -2657,34 +2657,11 @@ module Steep
2657
2657
  def synthesize_sendish(node, hint:, tapp:)
2658
2658
  case node.type
2659
2659
  when :send
2660
- yield_self do
2661
- if self_class?(node)
2662
- module_type = expand_alias(module_context.module_type)
2663
- type = if module_type.is_a?(AST::Types::Name::Singleton)
2664
- AST::Types::Name::Singleton.new(name: module_type.name)
2665
- else
2666
- module_type
2667
- end
2668
-
2669
- add_typing(node, type: type)
2670
- else
2671
- type_send(node, send_node: node, block_params: nil, block_body: nil, tapp: tapp, hint: hint)
2672
- end
2673
- end
2660
+ type_send(node, send_node: node, block_params: nil, block_body: nil, tapp: tapp, hint: hint)
2674
2661
  when :csend
2675
2662
  yield_self do
2676
2663
  send_type, constr =
2677
- if self_class?(node)
2678
- module_type = expand_alias(module_context.module_type)
2679
- type = if module_type.is_a?(AST::Types::Name::Singleton)
2680
- AST::Types::Name::Singleton.new(name: module_type.name)
2681
- else
2682
- module_type
2683
- end
2684
- add_typing(node, type: type).to_ary
2685
- else
2686
- type_send(node, send_node: node, block_params: nil, block_body: nil, unwrap: true, tapp: tapp, hint: hint).to_ary
2687
- end
2664
+ type_send(node, send_node: node, block_params: nil, block_body: nil, unwrap: true, tapp: tapp, hint: hint).to_ary
2688
2665
 
2689
2666
  constr
2690
2667
  .update_type_env { context.type_env.join(constr.context.type_env, context.type_env) }
@@ -4687,10 +4664,6 @@ module Steep
4687
4664
  add_typing node, type: AST::Builtin.any_type
4688
4665
  end
4689
4666
 
4690
- def self_class?(node)
4691
- node.type == :send && node.children[0]&.type == :self && node.children[1] == :class
4692
- end
4693
-
4694
4667
  def namespace_module?(node)
4695
4668
  # @type var nodes: Array[Parser::AST::Node]
4696
4669
  nodes =
@@ -4962,11 +4935,11 @@ module Steep
4962
4935
  each_child_node(hash_node) do |child|
4963
4936
  if child.type == :pair
4964
4937
  case child.children[0].type
4965
- when :sym
4938
+ when :sym, :int, :str, :true, :false
4966
4939
  key_node = child.children[0] #: Parser::AST::Node
4967
4940
  value_node = child.children[1] #: Parser::AST::Node
4968
4941
 
4969
- key = key_node.children[0] #: String | Symbol | Integer
4942
+ key = key_node.children[0] #: AST::Types::Record::key
4970
4943
 
4971
4944
  _, constr = constr.synthesize(key_node, hint: AST::Types::Literal.new(value: key))
4972
4945
 
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "1.8.0.pre.1"
2
+ VERSION = "1.8.0"
3
3
  end
data/lib/steep.rb CHANGED
@@ -75,6 +75,7 @@ require "steep/subtyping/constraints"
75
75
  require "steep/subtyping/variable_variance"
76
76
 
77
77
  require "steep/diagnostic/helper"
78
+ require "steep/diagnostic/result_printer2"
78
79
  require "steep/diagnostic/ruby"
79
80
  require "steep/diagnostic/signature"
80
81
  require "steep/diagnostic/lsp_formatter"
@@ -0,0 +1,15 @@
1
+ module LocationHelper : _WithLocation
2
+ interface _WithLocation
3
+ def location_method: () -> String
4
+ end
5
+
6
+ def hello: () -> void
7
+ end
8
+
9
+ class StringGeneric[X < Integer, Y < Integer = String]
10
+ def location_method: () -> Integer
11
+
12
+ include LocationHelper
13
+ extend LocationHelper
14
+ end
15
+
data/steep.gemspec CHANGED
@@ -36,7 +36,7 @@ Gem::Specification.new do |spec|
36
36
  spec.add_runtime_dependency "rainbow", ">= 2.2.2", "< 4.0"
37
37
  spec.add_runtime_dependency "listen", "~> 3.0"
38
38
  spec.add_runtime_dependency "language_server-protocol", ">= 3.15", "< 4.0"
39
- spec.add_runtime_dependency "rbs", "~> 3.6.0.dev"
39
+ spec.add_runtime_dependency "rbs", "~> 3.6.0"
40
40
  spec.add_runtime_dependency "concurrent-ruby", ">= 1.1.10"
41
41
  spec.add_runtime_dependency "terminal-table", ">= 2", "< 4"
42
42
  spec.add_runtime_dependency "securerandom", ">= 0.1"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: steep
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0.pre.1
4
+ version: 1.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soutaro Matsumoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-17 00:00:00.000000000 Z
11
+ date: 2024-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -98,14 +98,14 @@ dependencies:
98
98
  requirements:
99
99
  - - "~>"
100
100
  - !ruby/object:Gem::Version
101
- version: 3.6.0.dev
101
+ version: 3.6.0
102
102
  type: :runtime
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
105
105
  requirements:
106
106
  - - "~>"
107
107
  - !ruby/object:Gem::Version
108
- version: 3.6.0.dev
108
+ version: 3.6.0
109
109
  - !ruby/object:Gem::Dependency
110
110
  name: concurrent-ruby
111
111
  requirement: !ruby/object:Gem::Requirement
@@ -291,6 +291,7 @@ files:
291
291
  - lib/steep/diagnostic/deprecated/unknown_constant_assigned.rb
292
292
  - lib/steep/diagnostic/helper.rb
293
293
  - lib/steep/diagnostic/lsp_formatter.rb
294
+ - lib/steep/diagnostic/result_printer2.rb
294
295
  - lib/steep/diagnostic/ruby.rb
295
296
  - lib/steep/diagnostic/signature.rb
296
297
  - lib/steep/drivers/annotations.rb
@@ -384,6 +385,7 @@ files:
384
385
  - sample/lib/conference.rb
385
386
  - sample/lib/length.rb
386
387
  - sample/sig/conference.rbs
388
+ - sample/sig/generics.rbs
387
389
  - sample/sig/length.rbs
388
390
  - steep.gemspec
389
391
  homepage: https://github.com/soutaro/steep
@@ -408,7 +410,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
408
410
  - !ruby/object:Gem::Version
409
411
  version: '0'
410
412
  requirements: []
411
- rubygems_version: 3.5.17
413
+ rubygems_version: 3.5.11
412
414
  signing_key:
413
415
  specification_version: 4
414
416
  summary: Gradual Typing for Ruby