Class: T::Types::Base
- Inherits:
-
Object
- Object
- T::Types::Base
- Defined in:
- lib/types/types/base.rb
Direct Known Subclasses
Private::Types::NotTyped, Private::Types::StringHolder, Private::Types::TypeAlias, Private::Types::Void, Anything, AttachedClassType, ClassOf, Enum, FixedArray, FixedHash, Intersection, NoReturn, Proc, SelfType, Simple, TEnum, TypeParameter, TypeVariable, TypedClass, TypedEnumerable, TypedModule, Union, Untyped
Class Method Summary collapse
Instance Method Summary collapse
-
#==(other) ⇒ Object
(also: #eql?)
Type equivalence, defined by serializing the type to a string (with ‘#name`) and comparing the resulting strings for equality.
- #describe_obj(obj) ⇒ Object
- #error_message_for_obj(obj) ⇒ Object
- #error_message_for_obj_recursive(obj) ⇒ Object
-
#hash ⇒ Object
Equality methods (necessary for deduping types with ‘uniq`).
-
#recursively_valid?(obj) ⇒ Boolean
this will be redefined in certain subclasses.
-
#subtype_of?(t2) ⇒ Boolean
Mirrors ruby_typer::core::Types::isSubType See git.corp.stripe.com/stripe-internal/ruby-typer/blob/9fc8ed998c04ac0b96592ae6bb3493b8a925c5c1/core/types/subtyping.cc#L912-L950.
- #to_s ⇒ Object
- #validate!(obj) ⇒ Object
Class Method Details
.method_added(method_name) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 |
# File 'lib/types/types/base.rb', line 6 def self.method_added(method_name) super(method_name) # What is now `subtype_of_single?` used to be named `subtype_of?`. Make sure people don't # override the wrong thing. # # NB: Outside of T::Types, we would enforce this by using `sig` and not declaring the method # as overridable, but doing so here would result in a dependency cycle. if method_name == :subtype_of? && self != T::Types::Base raise "`subtype_of?` should not be overridden. You probably want to override " \ "`subtype_of_single?` instead." end end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
Type equivalence, defined by serializing the type to a string (with ‘#name`) and comparing the resulting strings for equality.
191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/types/types/base.rb', line 191 def ==(other) case other when T::Types::Base # Performance fast path: pooled and memoized type instances (e.g. the # results of repeated T.nilable(X) calls) are the same object, so they # can compare equal without computing and comparing their names. other.equal?(self) || other.name == self.name else false end end |
#describe_obj(obj) ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/types/types/base.rb', line 136 def describe_obj(obj) # Would be redundant to print class and value in these common cases. case obj when nil, true, false return "type #{obj.class}" end # In rare cases, obj.inspect may fail, or be undefined, so rescue. begin # Default inspect behavior of, eg; `#<Object:0x0...>` is ugly; just print the hash instead, which is more concise/readable. if obj.method(:inspect).owner == Kernel "type #{obj.class} with hash #{obj.hash}" elsif T::Configuration.include_value_in_type_errors? "type #{obj.class} with value #{T::Utils.string_truncate_middle(obj.inspect, 30, 30)}" else "type #{obj.class}" end rescue StandardError, SystemStackError "type #{obj.class} with unprintable value" end end |
#error_message_for_obj(obj) ⇒ Object
158 159 160 161 162 163 164 |
# File 'lib/types/types/base.rb', line 158 def (obj) if valid?(obj) nil else (obj) end end |
#error_message_for_obj_recursive(obj) ⇒ Object
166 167 168 169 170 171 172 |
# File 'lib/types/types/base.rb', line 166 def (obj) if recursively_valid?(obj) nil else (obj) end end |
#hash ⇒ Object
Equality methods (necessary for deduping types with ‘uniq`)
185 186 187 |
# File 'lib/types/types/base.rb', line 185 def hash name.hash end |
#recursively_valid?(obj) ⇒ Boolean
this will be redefined in certain subclasses
20 21 22 |
# File 'lib/types/types/base.rb', line 20 def recursively_valid?(obj) valid?(obj) end |
#subtype_of?(t2) ⇒ Boolean
Mirrors ruby_typer::core::Types::isSubType See git.corp.stripe.com/stripe-internal/ruby-typer/blob/9fc8ed998c04ac0b96592ae6bb3493b8a925c5c1/core/types/subtyping.cc#L912-L950
This method cannot be overridden (see ‘method_added` above). Subclasses only need to implement `subtype_of_single?`).
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/types/types/base.rb', line 52 def subtype_of?(t2) t1 = self # Fast path over the isSubType mirror below: the dominant pair during # override validation is two plain Simples, which match none of the # branches in the walk. instance_of? (never # is_a?) so that any hypothetical Simple subclass takes the full walk, # and the raw subtype_of_single? result is returned unmodified # (Module#<= yields nil for unrelated modules, which callers observe). if t1.instance_of?(T::Types::Simple) && t2.instance_of?(T::Types::Simple) return subtype_of_single?(t2) end if t2.is_a?(T::Private::Types::TypeAlias) t2 = t2.aliased_type end if t2.is_a?(T::Types::Anything) return true end if t1.is_a?(T::Private::Types::TypeAlias) return t1.aliased_type.subtype_of?(t2) end if t1.is_a?(T::Types::TypeVariable) || t2.is_a?(T::Types::TypeVariable) # Generics are erased at runtime. Let's treat them like `T.untyped` for # the purpose of things like override checking. return true end # pairs to cover: 1 (_, _) # 2 (_, And) # 3 (_, Or) # 4 (And, _) # 5 (And, And) # 6 (And, Or) # 7 (Or, _) # 8 (Or, And) # 9 (Or, Or) # Note: order of cases here matters! if t1.is_a?(T::Types::Union) # 7, 8, 9 # this will be incorrect if/when we have Type members return t1.types.all? { |t1_member| t1_member.subtype_of?(t2) } end if t2.is_a?(T::Types::Intersection) # 2, 5 # this will be incorrect if/when we have Type members return t2.types.all? { |t2_member| t1.subtype_of?(t2_member) } end if t2.is_a?(T::Types::Union) if t1.is_a?(T::Types::Intersection) # 6 # dropping either of parts eagerly make subtype test be too strict. # we have to try both cases, when we normally try only one return t2.types.any? { |t2_member| t1.subtype_of?(t2_member) } || t1.types.any? { |t1_member| t1_member.subtype_of?(t2) } end return t2.types.any? { |t2_member| t1.subtype_of?(t2_member) } # 3 end if t1.is_a?(T::Types::Intersection) # 4 # this will be incorrect if/when we have Type members return t1.types.any? { |t1_member| t1_member.subtype_of?(t2) } end # 1; Start with some special cases if t1.is_a?(T::Private::Types::Void) return t2.is_a?(T::Private::Types::Void) end if t1.is_a?(T::Types::Untyped) || t2.is_a?(T::Types::Untyped) return true end # Rest of (1) subtype_of_single?(t2) end |
#to_s ⇒ Object
132 133 134 |
# File 'lib/types/types/base.rb', line 132 def to_s name end |
#validate!(obj) ⇒ Object
178 179 180 181 |
# File 'lib/types/types/base.rb', line 178 def validate!(obj) err = (obj) raise TypeError.new(err) if err end |