rigortype 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/data/builtins/ruby_core/array.yml +1470 -0
  3. data/data/builtins/ruby_core/file.yml +501 -0
  4. data/data/builtins/ruby_core/io.yml +1594 -0
  5. data/data/builtins/ruby_core/numeric.yml +1809 -0
  6. data/data/builtins/ruby_core/string.yml +1850 -0
  7. data/lib/rigor/analysis/check_rules.rb +297 -5
  8. data/lib/rigor/analysis/diagnostic.rb +13 -2
  9. data/lib/rigor/analysis/runner.rb +52 -5
  10. data/lib/rigor/builtins/imported_refinements.rb +69 -0
  11. data/lib/rigor/cli/type_of_command.rb +11 -5
  12. data/lib/rigor/cli/type_scan_command.rb +13 -8
  13. data/lib/rigor/cli.rb +26 -6
  14. data/lib/rigor/configuration.rb +18 -2
  15. data/lib/rigor/environment.rb +3 -1
  16. data/lib/rigor/inference/acceptance.rb +180 -0
  17. data/lib/rigor/inference/builtins/array_catalog.rb +46 -0
  18. data/lib/rigor/inference/builtins/method_catalog.rb +90 -0
  19. data/lib/rigor/inference/builtins/numeric_catalog.rb +93 -0
  20. data/lib/rigor/inference/builtins/string_catalog.rb +39 -0
  21. data/lib/rigor/inference/expression_typer.rb +151 -0
  22. data/lib/rigor/inference/method_dispatcher/constant_folding.rb +650 -16
  23. data/lib/rigor/inference/method_dispatcher/file_folding.rb +144 -0
  24. data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +113 -0
  25. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +4 -0
  26. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +107 -0
  27. data/lib/rigor/inference/method_dispatcher.rb +28 -21
  28. data/lib/rigor/inference/narrowing.rb +471 -10
  29. data/lib/rigor/inference/scope_indexer.rb +66 -0
  30. data/lib/rigor/inference/statement_evaluator.rb +305 -2
  31. data/lib/rigor/rbs_extended.rb +174 -14
  32. data/lib/rigor/scope.rb +44 -5
  33. data/lib/rigor/type/combinator.rb +69 -1
  34. data/lib/rigor/type/difference.rb +155 -0
  35. data/lib/rigor/type/integer_range.rb +137 -0
  36. data/lib/rigor/type.rb +2 -0
  37. data/lib/rigor/version.rb +1 -1
  38. data/sig/rigor/inference.rbs +5 -2
  39. data/sig/rigor/rbs_extended.rbs +25 -1
  40. data/sig/rigor/scope.rbs +4 -0
  41. data/sig/rigor/type.rbs +51 -1
  42. metadata +15 -1
@@ -6,9 +6,11 @@ require_relative "dynamic"
6
6
  require_relative "nominal"
7
7
  require_relative "singleton"
8
8
  require_relative "constant"
9
+ require_relative "integer_range"
9
10
  require_relative "tuple"
10
11
  require_relative "hash_shape"
11
12
  require_relative "union"
13
+ require_relative "difference"
12
14
 
13
15
  module Rigor
14
16
  module Type
@@ -20,7 +22,7 @@ module Rigor
20
22
  #
21
23
  # See docs/internal-spec/internal-type-api.md and
22
24
  # docs/type-specification/normalization.md.
23
- module Combinator
25
+ module Combinator # rubocop:disable Metrics/ModuleLength
24
26
  module_function
25
27
 
26
28
  def top
@@ -65,6 +67,72 @@ module Rigor
65
67
  Constant.new(value)
66
68
  end
67
69
 
70
+ # Bounded-integer carrier. Each bound is either an `Integer` or
71
+ # one of `:neg_infinity` / `:pos_infinity` (sentinels exposed as
72
+ # `IntegerRange::NEG_INFINITY` / `POS_INFINITY`).
73
+ def integer_range(min, max)
74
+ IntegerRange.new(min, max)
75
+ end
76
+
77
+ # Convenience aliases for the most common bounded shapes. The
78
+ # named alias survives roundtrip through `describe` for nicer
79
+ # human-facing output.
80
+ def positive_int
81
+ IntegerRange.new(1, IntegerRange::POS_INFINITY)
82
+ end
83
+
84
+ def non_negative_int
85
+ IntegerRange.new(0, IntegerRange::POS_INFINITY)
86
+ end
87
+
88
+ def negative_int
89
+ IntegerRange.new(IntegerRange::NEG_INFINITY, -1)
90
+ end
91
+
92
+ def non_positive_int
93
+ IntegerRange.new(IntegerRange::NEG_INFINITY, 0)
94
+ end
95
+
96
+ def universal_int
97
+ IntegerRange.new(IntegerRange::NEG_INFINITY, IntegerRange::POS_INFINITY)
98
+ end
99
+
100
+ # Point-removal refinement carrier (ADR-3 OQ3 Option C). Use
101
+ # `non_empty_string` / `non_zero_int` / `non_empty_array` /
102
+ # `non_empty_hash` for the imported built-in shapes; raw
103
+ # `difference(base, removed)` for ad-hoc refinements an
104
+ # `RBS::Extended` annotation introduces.
105
+ def difference(base, removed)
106
+ Difference.new(base, removed)
107
+ end
108
+
109
+ def non_empty_string
110
+ Difference.new(nominal_of("String"), constant_of(""))
111
+ end
112
+
113
+ def non_zero_int
114
+ Difference.new(nominal_of("Integer"), constant_of(0))
115
+ end
116
+
117
+ # `non-empty-array[T]` requires the element type so the
118
+ # `Nominal[Array, [T]]` projection through Array#first /
119
+ # #last keeps element precision intact. The default
120
+ # `Top` admits any array element when the caller does
121
+ # not have a more specific element type.
122
+ def non_empty_array(element = top)
123
+ Difference.new(
124
+ nominal_of("Array", type_args: [element]),
125
+ tuple_of
126
+ )
127
+ end
128
+
129
+ def non_empty_hash(key = top, value = top)
130
+ Difference.new(
131
+ nominal_of("Hash", type_args: [key, value]),
132
+ hash_shape_of({})
133
+ )
134
+ end
135
+
68
136
  # Constructs a heterogeneous, fixed-arity Tuple from positional
69
137
  # element types. `tuple_of()` produces the empty tuple `Tuple[]`,
70
138
  # which is structurally distinct from the raw `Nominal[Array]`.
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../trinary"
4
+
5
+ module Rigor
6
+ module Type
7
+ # `Difference[base, removed]` — the value set of `base` minus
8
+ # the value set of `removed`. Implements the point-removal
9
+ # half of the OQ3 refinement-carrier strategy
10
+ # ([ADR-3](docs/adr/3-type-representation.md), Working
11
+ # Decision Option C):
12
+ #
13
+ # non-empty-string = Difference[Nominal[String], Constant[""]]
14
+ # non-zero-int = Difference[Nominal[Integer], Constant[0]]
15
+ # non-empty-array[T] = Difference[Nominal[Array, [T]], Tuple[]]
16
+ # non-empty-hash[K,V] = Difference[Nominal[Hash, [K,V]], HashShape{}]
17
+ #
18
+ # The carrier itself is structural: it stores `base` and
19
+ # `removed` as inner `Type` references and answers projection
20
+ # / acceptance / display questions by composing those inner
21
+ # answers per the lattice algebra in
22
+ # [`value-lattice.md`](docs/type-specification/value-lattice.md).
23
+ # The canonical-name registry (display side) lives in
24
+ # `Rigor::Type::Combinator` and prints kebab-case names like
25
+ # `non-empty-string` for the recognised shapes; unrecognised
26
+ # differences fall back to the raw `base - removed`
27
+ # operator form per [`type-operators.md`](docs/type-specification/type-operators.md).
28
+ #
29
+ # Construction goes through `Type::Combinator.difference` /
30
+ # `Combinator.non_empty_string` etc. — direct `.new` calls
31
+ # are an internal contract; callers MUST ensure both bounds
32
+ # are valid `Rigor::Type` values and that `removed` is a
33
+ # subtype-or-equal of `base` (otherwise the difference does
34
+ # not narrow anything and a normalisation upstream should
35
+ # collapse to `base`).
36
+ class Difference
37
+ attr_reader :base, :removed
38
+
39
+ def initialize(base, removed)
40
+ @base = base
41
+ @removed = removed
42
+ freeze
43
+ end
44
+
45
+ def describe(verbosity = :short)
46
+ named = canonical_name
47
+ return named if named
48
+
49
+ "#{base.describe(verbosity)} - #{removed.describe(verbosity)}"
50
+ end
51
+
52
+ # Erases to the base nominal: every refinement MUST erase
53
+ # to its base per [`rbs-erasure.md`](docs/type-specification/rbs-erasure.md).
54
+ def erase_to_rbs
55
+ base.erase_to_rbs
56
+ end
57
+
58
+ def top
59
+ Trinary.no
60
+ end
61
+
62
+ def bot
63
+ Trinary.no
64
+ end
65
+
66
+ def dynamic
67
+ base.respond_to?(:dynamic) ? base.dynamic : Trinary.no
68
+ end
69
+
70
+ def accepts(other, mode: :gradual)
71
+ Inference::Acceptance.accepts(self, other, mode: mode)
72
+ end
73
+
74
+ def ==(other)
75
+ other.is_a?(Difference) && base == other.base && removed == other.removed
76
+ end
77
+ alias eql? ==
78
+
79
+ def hash
80
+ [Difference, base, removed].hash
81
+ end
82
+
83
+ def inspect
84
+ "#<Rigor::Type::Difference #{describe(:short)}>"
85
+ end
86
+
87
+ private
88
+
89
+ # Renders the kebab-case shorthand for recognised
90
+ # imported-built-in shapes. Parameterised bases keep their
91
+ # type-args in the canonical form (`non-empty-array[T]`,
92
+ # `non-empty-hash[K, V]`) so element-precision survives the
93
+ # display round-trip. Unrecognised shapes fall back to the
94
+ # raw `base - removed` operator form.
95
+ #
96
+ # The recognised set is kept in sync with the imported-built-in
97
+ # catalogue ([`imported-built-in-types.md`](docs/type-specification/imported-built-in-types.md)).
98
+ def canonical_name
99
+ return nil unless base.is_a?(Nominal)
100
+
101
+ send(CANONICAL_HANDLERS[base.class_name] || :no_canonical_name)
102
+ end
103
+
104
+ CANONICAL_HANDLERS = {
105
+ "String" => :string_canonical_name,
106
+ "Integer" => :integer_canonical_name,
107
+ "Array" => :array_canonical_name_if_empty,
108
+ "Hash" => :hash_canonical_name_if_empty
109
+ }.freeze
110
+ private_constant :CANONICAL_HANDLERS
111
+
112
+ def no_canonical_name
113
+ nil
114
+ end
115
+
116
+ def string_canonical_name
117
+ return nil unless removed.is_a?(Constant) && removed.value == ""
118
+
119
+ "non-empty-string"
120
+ end
121
+
122
+ def integer_canonical_name
123
+ return nil unless removed.is_a?(Constant) && removed.value.is_a?(Integer) && removed.value.zero?
124
+
125
+ "non-zero-int"
126
+ end
127
+
128
+ def array_canonical_name_if_empty
129
+ return nil unless removed.is_a?(Tuple) && removed.elements.empty?
130
+
131
+ array_canonical_name
132
+ end
133
+
134
+ def hash_canonical_name_if_empty
135
+ return nil unless removed.is_a?(HashShape) && removed.pairs.empty?
136
+
137
+ hash_canonical_name
138
+ end
139
+
140
+ def array_canonical_name
141
+ elem = base.type_args.first
142
+ return "non-empty-array" if elem.nil?
143
+
144
+ "non-empty-array[#{elem.describe}]"
145
+ end
146
+
147
+ def hash_canonical_name
148
+ key, value = base.type_args
149
+ return "non-empty-hash" if key.nil? || value.nil?
150
+
151
+ "non-empty-hash[#{key.describe}, #{value.describe}]"
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../trinary"
4
+
5
+ module Rigor
6
+ module Type
7
+ # A bounded integer range carrier. Each bound is either an `Integer`
8
+ # or one of the symbolic infinities `:neg_infinity` / `:pos_infinity`.
9
+ # Inspired by PHPStan's `int<min, max>` family — the named aliases
10
+ # `positive-int` (1..), `non-negative-int` (0..), `negative-int`
11
+ # (..-1), `non-positive-int` (..0) all surface through this single
12
+ # carrier and are recovered in `describe` for human-friendly output.
13
+ #
14
+ # Constraints on construction:
15
+ # - both bounds must be either `Integer` or one of the two infinity
16
+ # sentinels;
17
+ # - if both bounds are concrete, `min <= max` must hold;
18
+ # - the universal case `(-∞, +∞)` is structurally distinct from
19
+ # `Nominal[Integer]` — it carries no extra information today but
20
+ # keeps the carrier closed under range narrowing.
21
+ #
22
+ # Erasure to RBS is always "Integer": RBS itself does not natively
23
+ # express bounded integer ranges.
24
+ class IntegerRange
25
+ NEG_INFINITY = :neg_infinity
26
+ POS_INFINITY = :pos_infinity
27
+ INFINITIES = [NEG_INFINITY, POS_INFINITY].freeze
28
+
29
+ attr_reader :min, :max
30
+
31
+ def initialize(min, max)
32
+ validate_bound!(min, "min")
33
+ validate_bound!(max, "max")
34
+ if min.is_a?(Integer) && max.is_a?(Integer) && min > max
35
+ raise ArgumentError, "IntegerRange requires min (#{min}) <= max (#{max})"
36
+ end
37
+ if min == POS_INFINITY || max == NEG_INFINITY
38
+ raise ArgumentError, "IntegerRange bounds out of order: min=#{min.inspect}, max=#{max.inspect}"
39
+ end
40
+
41
+ @min = min
42
+ @max = max
43
+ freeze
44
+ end
45
+
46
+ def universal?
47
+ min == NEG_INFINITY && max == POS_INFINITY
48
+ end
49
+
50
+ def finite?
51
+ min.is_a?(Integer) && max.is_a?(Integer)
52
+ end
53
+
54
+ def cardinality
55
+ finite? ? (max - min + 1) : Float::INFINITY
56
+ end
57
+
58
+ def covers?(int)
59
+ return false unless int.is_a?(Integer)
60
+
61
+ int.between?(lower, upper)
62
+ end
63
+
64
+ # Returns the lower bound as a numeric (with `-Float::INFINITY` for
65
+ # `:neg_infinity`). Use this in arithmetic comparisons; never compare
66
+ # `:neg_infinity` directly with an `Integer`.
67
+ def lower
68
+ min == NEG_INFINITY ? -Float::INFINITY : min
69
+ end
70
+
71
+ def upper
72
+ max == POS_INFINITY ? Float::INFINITY : max
73
+ end
74
+
75
+ ALIAS_NAMES = {
76
+ [NEG_INFINITY, POS_INFINITY] => "int",
77
+ [1, POS_INFINITY] => "positive-int",
78
+ [0, POS_INFINITY] => "non-negative-int",
79
+ [NEG_INFINITY, -1] => "negative-int",
80
+ [NEG_INFINITY, 0] => "non-positive-int"
81
+ }.freeze
82
+
83
+ def describe(_verbosity = :short)
84
+ ALIAS_NAMES[[min, max]] || generic_description
85
+ end
86
+
87
+ def generic_description
88
+ return "int<#{min}, max>" if max == POS_INFINITY
89
+ return "int<min, #{max}>" if min == NEG_INFINITY
90
+
91
+ "int<#{min}, #{max}>"
92
+ end
93
+
94
+ def erase_to_rbs
95
+ "Integer"
96
+ end
97
+
98
+ def top
99
+ Trinary.no
100
+ end
101
+
102
+ def bot
103
+ Trinary.no
104
+ end
105
+
106
+ def dynamic
107
+ Trinary.no
108
+ end
109
+
110
+ def accepts(other, mode: :gradual)
111
+ Inference::Acceptance.accepts(self, other, mode: mode)
112
+ end
113
+
114
+ def ==(other)
115
+ other.is_a?(IntegerRange) && min == other.min && max == other.max
116
+ end
117
+ alias eql? ==
118
+
119
+ def hash
120
+ [IntegerRange, min, max].hash
121
+ end
122
+
123
+ def inspect
124
+ "#<Rigor::Type::IntegerRange #{describe(:short)}>"
125
+ end
126
+
127
+ private
128
+
129
+ def validate_bound!(bound, label)
130
+ return if bound.is_a?(Integer) || INFINITIES.include?(bound)
131
+
132
+ raise ArgumentError,
133
+ "IntegerRange #{label} must be Integer or :neg_infinity/:pos_infinity, got #{bound.inspect}"
134
+ end
135
+ end
136
+ end
137
+ end
data/lib/rigor/type.rb CHANGED
@@ -16,8 +16,10 @@ require_relative "type/dynamic"
16
16
  require_relative "type/nominal"
17
17
  require_relative "type/singleton"
18
18
  require_relative "type/constant"
19
+ require_relative "type/integer_range"
19
20
  require_relative "type/tuple"
20
21
  require_relative "type/hash_shape"
21
22
  require_relative "type/union"
23
+ require_relative "type/difference"
22
24
  require_relative "type/accepts_result"
23
25
  require_relative "type/combinator"
data/lib/rigor/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rigor
4
- VERSION = "0.0.1"
4
+ VERSION = "0.0.3"
5
5
  end
@@ -138,14 +138,17 @@ module Rigor
138
138
  end
139
139
 
140
140
  class CoverageScanner
141
- class Stats
141
+ class Result
142
+ attr_reader visits: Hash[Class, Integer]
143
+ attr_reader unrecognized: Hash[Class, Integer]
144
+ attr_reader events: Array[Fallback]
142
145
  def visited_count: () -> Integer
143
146
  def unrecognized_count: () -> Integer
144
147
  def unrecognized_ratio: () -> Float
145
148
  end
146
149
 
147
150
  def initialize: (?scope: Scope?) -> void
148
- def scan: (untyped root) -> Stats
151
+ def scan: (untyped root) -> Result
149
152
  end
150
153
  end
151
154
  end
@@ -10,13 +10,37 @@ module Rigor
10
10
  attr_reader target_kind: target_kind
11
11
  attr_reader target_name: Symbol
12
12
  attr_reader class_name: String
13
+ attr_reader negative: bool
13
14
 
14
- def self.new: (edge: predicate_edge, target_kind: target_kind, target_name: Symbol, class_name: String) -> PredicateEffect
15
+ def self.new: (edge: predicate_edge, target_kind: target_kind, target_name: Symbol, class_name: String, negative: bool) -> PredicateEffect
15
16
  def truthy_only?: () -> bool
16
17
  def falsey_only?: () -> bool
18
+ def negative?: () -> bool
17
19
  end
18
20
 
19
21
  def self?.read_predicate_effects: (untyped method_def) -> Array[PredicateEffect]
20
22
  def self?.parse_predicate_annotation: (String string) -> PredicateEffect?
23
+
24
+ type assert_condition = :always | :if_truthy_return | :if_falsey_return
25
+
26
+ class AssertEffect
27
+ attr_reader condition: assert_condition
28
+ attr_reader target_kind: target_kind
29
+ attr_reader target_name: Symbol
30
+ attr_reader class_name: String
31
+ attr_reader negative: bool
32
+
33
+ def self.new: (condition: assert_condition, target_kind: target_kind, target_name: Symbol, class_name: String, negative: bool) -> AssertEffect
34
+ def always?: () -> bool
35
+ def if_truthy_return?: () -> bool
36
+ def if_falsey_return?: () -> bool
37
+ def negative?: () -> bool
38
+ end
39
+
40
+ def self?.read_assert_effects: (untyped method_def) -> Array[AssertEffect]
41
+ def self?.parse_assert_annotation: (String string) -> AssertEffect?
42
+
43
+ def self?.read_return_type_override: (untyped method_def) -> Type::t?
44
+ def self?.parse_return_type_override: (String string) -> Type::t?
21
45
  end
22
46
  end
data/sig/rigor/scope.rbs CHANGED
@@ -14,6 +14,7 @@ module Rigor
14
14
  attr_reader discovered_classes: Hash[String, Type::Singleton]
15
15
  attr_reader in_source_constants: Hash[String, Type::t]
16
16
  attr_reader discovered_methods: Hash[String, Hash[Symbol, Symbol]]
17
+ attr_reader discovered_def_nodes: Hash[String, Hash[Symbol, untyped]]
17
18
 
18
19
  def self.empty: (?environment: Environment) -> Scope
19
20
 
@@ -35,6 +36,9 @@ module Rigor
35
36
  def with_in_source_constants: (Hash[String, Type::t] table) -> Scope
36
37
  def with_discovered_methods: (Hash[String, Hash[Symbol, Symbol]] table) -> Scope
37
38
  def discovered_method?: (String | Symbol class_name, String | Symbol method_name, Symbol kind) -> bool
39
+ def with_discovered_def_nodes: (Hash[String, Hash[Symbol, untyped]] table) -> Scope
40
+ def user_def_for: (String | Symbol class_name, String | Symbol method_name) -> untyped?
41
+ def top_level_def_for: (String | Symbol method_name) -> untyped?
38
42
  def with_fact: (Analysis::FactStore::Fact fact) -> Scope
39
43
  def with_self_type: (Type::t? type) -> Scope
40
44
  def with_declared_types: (Hash[untyped, Type::t] table) -> Scope
data/sig/rigor/type.rbs CHANGED
@@ -1,6 +1,6 @@
1
1
  module Rigor
2
2
  module Type
3
- type t = Top | Bot | Dynamic | Constant | Nominal | Singleton | Union | Tuple | HashShape
3
+ type t = Top | Bot | Dynamic | Constant | IntegerRange | Nominal | Singleton | Union | Difference | Tuple | HashShape
4
4
 
5
5
  type accepts_mode = :strict | :gradual | :loose
6
6
 
@@ -58,6 +58,30 @@ module Rigor
58
58
  def inspect: () -> String
59
59
  end
60
60
 
61
+ class IntegerRange
62
+ NEG_INFINITY: Symbol
63
+ POS_INFINITY: Symbol
64
+ attr_reader min: (Integer | Symbol)
65
+ attr_reader max: (Integer | Symbol)
66
+ def initialize: ((Integer | Symbol) min, (Integer | Symbol) max) -> void
67
+ def universal?: () -> bool
68
+ def finite?: () -> bool
69
+ def cardinality: () -> (Integer | Float)
70
+ def covers?: (untyped value) -> bool
71
+ def lower: () -> Numeric
72
+ def upper: () -> Numeric
73
+ def describe: (?Symbol verbosity) -> String
74
+ def generic_description: () -> String
75
+ def erase_to_rbs: () -> String
76
+ def top: () -> Top
77
+ def bot: () -> Bot
78
+ def dynamic: () -> Dynamic
79
+ def accepts: (Type::t other, ?mode: accepts_mode) -> AcceptsResult
80
+ def ==: (untyped other) -> bool
81
+ def hash: () -> Integer
82
+ def inspect: () -> String
83
+ end
84
+
61
85
  class Nominal
62
86
  attr_reader class_name: String
63
87
  attr_reader type_args: Array[Type::t]
@@ -101,6 +125,21 @@ module Rigor
101
125
  def inspect: () -> String
102
126
  end
103
127
 
128
+ class Difference
129
+ attr_reader base: Type::t
130
+ attr_reader removed: Type::t
131
+ def initialize: (Type::t base, Type::t removed) -> void
132
+ def describe: (?Symbol verbosity) -> String
133
+ def erase_to_rbs: () -> String
134
+ def top: () -> Top
135
+ def bot: () -> Bot
136
+ def dynamic: () -> Dynamic
137
+ def accepts: (Type::t other, ?mode: accepts_mode) -> AcceptsResult
138
+ def ==: (untyped other) -> bool
139
+ def hash: () -> Integer
140
+ def inspect: () -> String
141
+ end
142
+
104
143
  class Tuple
105
144
  attr_reader elements: Array[Type::t]
106
145
  def initialize: (Array[Type::t] elements) -> void
@@ -163,6 +202,17 @@ module Rigor
163
202
  def self?.nominal_of: (Module | String class_name_or_object, ?type_args: Array[Type::t]) -> Nominal
164
203
  def self?.singleton_of: (Module | String class_name_or_object) -> Singleton
165
204
  def self?.constant_of: (untyped value) -> Constant
205
+ def self?.difference: (Type::t base, Type::t removed) -> Difference
206
+ def self?.non_empty_string: () -> Difference
207
+ def self?.non_zero_int: () -> Difference
208
+ def self?.non_empty_array: (?Type::t element) -> Difference
209
+ def self?.non_empty_hash: (?Type::t key, ?Type::t value) -> Difference
210
+ def self?.integer_range: ((Integer | Symbol) min, (Integer | Symbol) max) -> IntegerRange
211
+ def self?.positive_int: () -> IntegerRange
212
+ def self?.non_negative_int: () -> IntegerRange
213
+ def self?.negative_int: () -> IntegerRange
214
+ def self?.non_positive_int: () -> IntegerRange
215
+ def self?.universal_int: () -> IntegerRange
166
216
  def self?.tuple_of: (*Type::t elements) -> Tuple
167
217
  def self?.hash_shape_of: (?Hash[untyped, Type::t]? pairs, **untyped options) -> HashShape
168
218
  def self?.union: (*Type::t types) -> Type::t
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rigortype
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rigor contributors
@@ -160,6 +160,11 @@ extra_rdoc_files: []
160
160
  files:
161
161
  - LICENSE
162
162
  - README.md
163
+ - data/builtins/ruby_core/array.yml
164
+ - data/builtins/ruby_core/file.yml
165
+ - data/builtins/ruby_core/io.yml
166
+ - data/builtins/ruby_core/numeric.yml
167
+ - data/builtins/ruby_core/string.yml
163
168
  - exe/rigor
164
169
  - lib/rigor.rb
165
170
  - lib/rigor/analysis/check_rules.rb
@@ -169,6 +174,7 @@ files:
169
174
  - lib/rigor/analysis/runner.rb
170
175
  - lib/rigor/ast.rb
171
176
  - lib/rigor/ast/type_node.rb
177
+ - lib/rigor/builtins/imported_refinements.rb
172
178
  - lib/rigor/cli.rb
173
179
  - lib/rigor/cli/type_of_command.rb
174
180
  - lib/rigor/cli/type_of_renderer.rb
@@ -182,6 +188,10 @@ files:
182
188
  - lib/rigor/environment/rbs_loader.rb
183
189
  - lib/rigor/inference/acceptance.rb
184
190
  - lib/rigor/inference/block_parameter_binder.rb
191
+ - lib/rigor/inference/builtins/array_catalog.rb
192
+ - lib/rigor/inference/builtins/method_catalog.rb
193
+ - lib/rigor/inference/builtins/numeric_catalog.rb
194
+ - lib/rigor/inference/builtins/string_catalog.rb
185
195
  - lib/rigor/inference/closure_escape_analyzer.rb
186
196
  - lib/rigor/inference/coverage_scanner.rb
187
197
  - lib/rigor/inference/expression_typer.rb
@@ -189,6 +199,8 @@ files:
189
199
  - lib/rigor/inference/fallback_tracer.rb
190
200
  - lib/rigor/inference/method_dispatcher.rb
191
201
  - lib/rigor/inference/method_dispatcher/constant_folding.rb
202
+ - lib/rigor/inference/method_dispatcher/file_folding.rb
203
+ - lib/rigor/inference/method_dispatcher/iterator_dispatch.rb
192
204
  - lib/rigor/inference/method_dispatcher/overload_selector.rb
193
205
  - lib/rigor/inference/method_dispatcher/rbs_dispatch.rb
194
206
  - lib/rigor/inference/method_dispatcher/shape_dispatch.rb
@@ -210,8 +222,10 @@ files:
210
222
  - lib/rigor/type/bot.rb
211
223
  - lib/rigor/type/combinator.rb
212
224
  - lib/rigor/type/constant.rb
225
+ - lib/rigor/type/difference.rb
213
226
  - lib/rigor/type/dynamic.rb
214
227
  - lib/rigor/type/hash_shape.rb
228
+ - lib/rigor/type/integer_range.rb
215
229
  - lib/rigor/type/nominal.rb
216
230
  - lib/rigor/type/singleton.rb
217
231
  - lib/rigor/type/top.rb