Ruby: include/ruby/internal/value_type.h Source File

Ruby 3.4.3p32 (2025-04-14 revision d0b7e5b6a04bde21ca483d20a1546b28b401c2d4)

value_type.h
Go to the documentation of this file.
1#ifndef RBIMPL_VALUE_TYPE_H /*-*-C++-*-vi:se ft=cpp:*/
2#define RBIMPL_VALUE_TYPE_H
23#include "ruby/internal/assume.h"
24#include "ruby/internal/attr/artificial.h"
25#include "ruby/internal/attr/cold.h"
26#include "ruby/internal/attr/enum_extensibility.h"
27#include "ruby/internal/attr/forceinline.h"
28#include "ruby/internal/attr/pure.h"
29#include "ruby/internal/cast.h"
30#include "ruby/internal/constant_p.h"
31#include "ruby/internal/core/rbasic.h"
32#include "ruby/internal/dllexport.h"
33#include "ruby/internal/error.h"
34#include "ruby/internal/has/builtin.h"
35#include "ruby/internal/special_consts.h"
36#include "ruby/internal/stdbool.h"
37#include "ruby/internal/value.h"
38#include "ruby/assert.h"
39
40#if defined(T_DATA)
41/*
42 * :!BEWARE!: (Recent?) Solaris' <nfs/nfs.h> have conflicting definition of
43 * T_DATA. Let us stop here. Please have a workaround like this:
44 *
45 * ```C
46 * #include <ruby/ruby.h> // <- Include this one first.
47 * #undef T_DATA // <- ... and stick to RUBY_T_DATA forever.
48 * #include <nfs/nfs.h> // <- OS-provided T_DATA introduced.
49 * ```
50 *
51 * See also [ruby-core:4261]
52 */
53# error Bail out due to conflicting definition of T_DATA.
54#endif
55
56#define T_ARRAY RUBY_T_ARRAY
57#define T_BIGNUM RUBY_T_BIGNUM
58#define T_CLASS RUBY_T_CLASS
59#define T_COMPLEX RUBY_T_COMPLEX
60#define T_DATA RUBY_T_DATA
61#define T_FALSE RUBY_T_FALSE
62#define T_FILE RUBY_T_FILE
63#define T_FIXNUM RUBY_T_FIXNUM
64#define T_FLOAT RUBY_T_FLOAT
65#define T_HASH RUBY_T_HASH
66#define T_ICLASS RUBY_T_ICLASS
67#define T_IMEMO RUBY_T_IMEMO
68#define T_MASK RUBY_T_MASK
69#define T_MATCH RUBY_T_MATCH
70#define T_MODULE RUBY_T_MODULE
71#define T_MOVED RUBY_T_MOVED
72#define T_NIL RUBY_T_NIL
73#define T_NODE RUBY_T_NODE
74#define T_NONE RUBY_T_NONE
75#define T_OBJECT RUBY_T_OBJECT
76#define T_RATIONAL RUBY_T_RATIONAL
77#define T_REGEXP RUBY_T_REGEXP
78#define T_STRING RUBY_T_STRING
79#define T_STRUCT RUBY_T_STRUCT
80#define T_SYMBOL RUBY_T_SYMBOL
81#define T_TRUE RUBY_T_TRUE
82#define T_UNDEF RUBY_T_UNDEF
83#define T_ZOMBIE RUBY_T_ZOMBIE
84
85#define BUILTIN_TYPE RB_BUILTIN_TYPE
86#define DYNAMIC_SYM_P RB_DYNAMIC_SYM_P
87#define RB_INTEGER_TYPE_P rb_integer_type_p
88#define SYMBOL_P RB_SYMBOL_P
89#define rb_type_p RB_TYPE_P
90
92#define RB_BUILTIN_TYPE RB_BUILTIN_TYPE
93#define RB_DYNAMIC_SYM_P RB_DYNAMIC_SYM_P
94#define RB_FLOAT_TYPE_P RB_FLOAT_TYPE_P
95#define RB_SYMBOL_P RB_SYMBOL_P
96#define RB_TYPE_P RB_TYPE_P
97#define Check_Type Check_Type
98
99#ifdef RBIMPL_VA_OPT_ARGS
100# define RBIMPL_ASSERT_TYPE(v, t) \
101 RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P(v, t), "actual type: %d", rb_type(v))
102#else
103# define RBIMPL_ASSERT_TYPE(v, t) RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P(v, t))
104#endif
106
108#define TYPE(_) RBIMPL_CAST((int)rb_type(_))
109
111 enum
112 RBIMPL_ATTR_ENUM_EXTENSIBILITY(closed)
113 ruby_value_type {
114 RUBY_T_NONE = 0x00,
115
116 RUBY_T_OBJECT = 0x01,
117 RUBY_T_CLASS = 0x02,
118 RUBY_T_MODULE = 0x03,
119 RUBY_T_FLOAT = 0x04,
120 RUBY_T_STRING = 0x05,
121 RUBY_T_REGEXP = 0x06,
122 RUBY_T_ARRAY = 0x07,
123 RUBY_T_HASH = 0x08,
124 RUBY_T_STRUCT = 0x09,
125 RUBY_T_BIGNUM = 0x0a,
126 RUBY_T_FILE = 0x0b,
127 RUBY_T_DATA = 0x0c,
128 RUBY_T_MATCH = 0x0d,
129 RUBY_T_COMPLEX = 0x0e,
130 RUBY_T_RATIONAL = 0x0f,
131
132 RUBY_T_NIL = 0x11,
133 RUBY_T_TRUE = 0x12,
134 RUBY_T_FALSE = 0x13,
135 RUBY_T_SYMBOL = 0x14,
136 RUBY_T_FIXNUM = 0x15,
137 RUBY_T_UNDEF = 0x16,
138
139 RUBY_T_IMEMO = 0x1a,
140 RUBY_T_NODE = 0x1b,
141 RUBY_T_ICLASS = 0x1c,
142 RUBY_T_ZOMBIE = 0x1d,
143 RUBY_T_MOVED = 0x1e,
144
145 RUBY_T_MASK = 0x1f
146};
147
148 RBIMPL_SYMBOL_EXPORT_BEGIN()
149 RBIMPL_ATTR_COLD()
169void rb_check_type(VALUE obj, int t);
170 RBIMPL_SYMBOL_EXPORT_END()
171
172 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
173 RBIMPL_ATTR_ARTIFICIAL()
181static inline enum ruby_value_type
182RB_BUILTIN_TYPE(VALUE obj)
183{
184 RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj));
185
186#if 0 && defined __GNUC__ && !defined __clang__
187 /* Don't move the access to `flags` before the preceding
188 * RB_SPECIAL_CONST_P check. */
189 __asm volatile("": : :"memory");
190#endif
191 VALUE ret = RBASIC(obj)->flags & RUBY_T_MASK;
192 return RBIMPL_CAST((enum ruby_value_type)ret);
193}
194
195 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
203static inline bool
204rb_integer_type_p(VALUE obj)
205{
206 if (RB_FIXNUM_P(obj)) {
207 return true;
208 }
209 else if (RB_SPECIAL_CONST_P(obj)) {
210 return false;
211 }
212 else {
213 return RB_BUILTIN_TYPE(obj) == RUBY_T_BIGNUM;
214 }
215}
216
217 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
224static inline enum ruby_value_type
225rb_type(VALUE obj)
226{
227 if (! RB_SPECIAL_CONST_P(obj)) {
228 return RB_BUILTIN_TYPE(obj);
229 }
230 else if (obj == RUBY_Qfalse) {
231 return RUBY_T_FALSE;
232 }
233 else if (obj == RUBY_Qnil) {
234 return RUBY_T_NIL;
235 }
236 else if (obj == RUBY_Qtrue) {
237 return RUBY_T_TRUE;
238 }
239 else if (obj == RUBY_Qundef) {
240 return RUBY_T_UNDEF;
241 }
242 else if (RB_FIXNUM_P(obj)) {
243 return RUBY_T_FIXNUM;
244 }
245 else if (RB_STATIC_SYM_P(obj)) {
246 return RUBY_T_SYMBOL;
247 }
248 else {
249 RBIMPL_ASSUME(RB_FLONUM_P(obj));
250 return RUBY_T_FLOAT;
251 }
252}
253
254 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
255 RBIMPL_ATTR_ARTIFICIAL()
263static inline bool
264RB_FLOAT_TYPE_P(VALUE obj)
265{
266 if (RB_FLONUM_P(obj)) {
267 return true;
268 }
269 else if (RB_SPECIAL_CONST_P(obj)) {
270 return false;
271 }
272 else {
273 return RB_BUILTIN_TYPE(obj) == RUBY_T_FLOAT;
274 }
275}
276
277 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
278 RBIMPL_ATTR_ARTIFICIAL()
286static inline bool
287RB_DYNAMIC_SYM_P(VALUE obj)
288{
289 if (RB_SPECIAL_CONST_P(obj)) {
290 return false;
291 }
292 else {
293 return RB_BUILTIN_TYPE(obj) == RUBY_T_SYMBOL;
294 }
295}
296
297 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
298 RBIMPL_ATTR_ARTIFICIAL()
306static inline bool
307RB_SYMBOL_P(VALUE obj)
308{
309 return RB_STATIC_SYM_P(obj) || RB_DYNAMIC_SYM_P(obj);
310}
311
312 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
313 RBIMPL_ATTR_ARTIFICIAL()
314 RBIMPL_ATTR_FORCEINLINE()
325static bool
326rbimpl_RB_TYPE_P_fastpath(VALUE obj, enum ruby_value_type t)
327{
328 if (t == RUBY_T_TRUE) {
329 return obj == RUBY_Qtrue;
330 }
331 else if (t == RUBY_T_FALSE) {
332 return obj == RUBY_Qfalse;
333 }
334 else if (t == RUBY_T_NIL) {
335 return obj == RUBY_Qnil;
336 }
337 else if (t == RUBY_T_UNDEF) {
338 return obj == RUBY_Qundef;
339 }
340 else if (t == RUBY_T_FIXNUM) {
341 return RB_FIXNUM_P(obj);
342 }
343 else if (t == RUBY_T_SYMBOL) {
344 return RB_SYMBOL_P(obj);
345 }
346 else if (t == RUBY_T_FLOAT) {
347 return RB_FLOAT_TYPE_P(obj);
348 }
349 else if (RB_SPECIAL_CONST_P(obj)) {
350 return false;
351 }
352 else if (t == RB_BUILTIN_TYPE(obj)) {
353 return true;
354 }
355 else {
356 return false;
357 }
358}
359
360 RBIMPL_ATTR_PURE_UNLESS_DEBUG()
361 RBIMPL_ATTR_ARTIFICIAL()
375static inline bool
376RB_TYPE_P(VALUE obj, enum ruby_value_type t)
377{
378 if (RBIMPL_CONSTANT_P(t)) {
379 return rbimpl_RB_TYPE_P_fastpath(obj, t);
380 }
381 else {
382 return t == rb_type(obj);
383 }
384}
385
387/* Clang, unlike GCC, cannot propagate __builtin_constant_p beyond function
388 * boundary. */
389#if defined(__clang__)
390# undef RB_TYPE_P
391# define RB_TYPE_P(obj, t) \
392 (RBIMPL_CONSTANT_P(t) ? \
393 rbimpl_RB_TYPE_P_fastpath((obj), (t)) : \
394 (RB_TYPE_P)((obj), (t)))
395#endif
396
397/* clang 3.x (4.2 compatible) can't eliminate CSE of RB_BUILTIN_TYPE
398 * in inline function and caller function
399 * See also 8998c06461ea0bef11b3aeb30b6d2ab71c8762ba
400 */
401#if RBIMPL_COMPILER_BEFORE(Clang, 4, 0, 0)
402# undef rb_integer_type_p
403# define rb_integer_type_p(obj) \
404 __extension__ ({ \
405 const VALUE integer_type_obj = (obj); \
406 (RB_FIXNUM_P(integer_type_obj) || \
407 (!RB_SPECIAL_CONST_P(integer_type_obj) && \
408 RB_BUILTIN_TYPE(integer_type_obj) == RUBY_T_BIGNUM)); \
409 })
410#endif
412
413 RBIMPL_ATTR_PURE()
414 RBIMPL_ATTR_ARTIFICIAL()
419static inline bool rbimpl_rtypeddata_p(VALUE obj);
420
421 RBIMPL_ATTR_ARTIFICIAL()
432static inline void
433Check_Type(VALUE v, enum ruby_value_type t)
434{
435 if (RB_UNLIKELY(! RB_TYPE_P(v, t))) {
436 goto unexpected_type;
437 }
438 else if (t == RUBY_T_DATA && rbimpl_rtypeddata_p(v)) {
439 /* Typed data is not simple `T_DATA`, see `rb_check_type` */
440 goto unexpected_type;
441 }
442 else {
443 return;
444 }
445
446 unexpected_type:
447 rb_unexpected_type(v, RBIMPL_CAST((int)t));
448}
449
450#endif /* RBIMPL_VALUE_TYPE_H */
artificial.h
Defines RBIMPL_ATTR_ARTIFICIAL.
RBIMPL_ATTR_ARTIFICIAL
#define RBIMPL_ATTR_ARTIFICIAL()
Wraps (or simulates) __attribute__((artificial))
Definition artificial.h:43
assert.h
RBIMPL_ASSERT_OR_ASSUME
#define RBIMPL_ASSERT_OR_ASSUME(...)
This is either RUBY_ASSERT or RBIMPL_ASSUME, depending on RUBY_DEBUG.
Definition assert.h:311
cold.h
Defines RBIMPL_ATTR_COLD.
RBIMPL_ATTR_COLD
#define RBIMPL_ATTR_COLD()
Wraps (or simulates) __attribute__((cold))
Definition cold.h:34
constant_p.h
Defines RBIMPL_CONSTANT_P.
RBIMPL_CONSTANT_P
#define RBIMPL_CONSTANT_P(expr)
Wraps (or simulates) __builtin_constant_p
Definition constant_p.h:35
dllexport.h
Tweaking visibility of C variables/functions.
RBIMPL_SYMBOL_EXPORT_END
#define RBIMPL_SYMBOL_EXPORT_END()
Counterpart of RBIMPL_SYMBOL_EXPORT_BEGIN.
Definition dllexport.h:74
RBIMPL_SYMBOL_EXPORT_BEGIN
#define RBIMPL_SYMBOL_EXPORT_BEGIN()
Shortcut macro equivalent to RUBY_SYMBOL_EXPORT_BEGIN extern "C" {.
Definition dllexport.h:65
enum_extensibility.h
RBIMPL_ATTR_ENUM_EXTENSIBILITY.
RBIMPL_ATTR_ENUM_EXTENSIBILITY
#define RBIMPL_ATTR_ENUM_EXTENSIBILITY(_)
Wraps (or simulates) __attribute__((enum_extensibility))
Definition enum_extensibility.h:29
forceinline.h
Defines RBIMPL_ATTR_FORCEINLINE.
RBIMPL_ATTR_FORCEINLINE
#define RBIMPL_ATTR_FORCEINLINE()
Wraps (or simulates) __forceinline.
Definition forceinline.h:37
rb_unexpected_type
void rb_unexpected_type(VALUE x, int t)
Fails with the given object's type incompatibility to the type.
Definition error.c:1360
rb_check_type
void rb_check_type(VALUE x, int t)
This was the old implementation of Check_Type(), but they diverged.
Definition error.c:1337
error.h
Declares rb_raise().
builtin.h
Defines RBIMPL_HAS_BUILTIN.
assume.h
Defines RBIMPL_ASSUME / RBIMPL_UNREACHABLE.
RBIMPL_ASSUME
#define RBIMPL_ASSUME(_)
Wraps (or simulates) __builtin_unreachable.
Definition assume.h:76
inline
#define inline
Old Visual Studio versions do not support the inline keyword, so we need to define it to be __inline.
Definition defines.h:88
pure.h
Defines RBIMPL_ATTR_PURE.
RBIMPL_ATTR_PURE
#define RBIMPL_ATTR_PURE()
Wraps (or simulates) __attribute__((pure))
Definition pure.h:33
RBIMPL_ATTR_PURE_UNLESS_DEBUG
#define RBIMPL_ATTR_PURE_UNLESS_DEBUG()
Enables RBIMPL_ATTR_PURE if and only if.
Definition pure.h:38
rbasic.h
Defines struct RBasic.
RBASIC
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
special_consts.h
Defines enum ruby_special_consts.
RB_STATIC_SYM_P
static bool RB_STATIC_SYM_P(VALUE obj)
Checks if the given object is a static symbol.
Definition special_consts.h:267
RB_FIXNUM_P
static bool RB_FIXNUM_P(VALUE obj)
Checks if the given object is a so-called Fixnum.
Definition special_consts.h:247
RB_SPECIAL_CONST_P
static bool RB_SPECIAL_CONST_P(VALUE obj)
Checks if the given object is of enum ruby_special_consts.
Definition special_consts.h:327
RUBY_Qtrue
@ RUBY_Qtrue
Definition special_consts.h:89
RUBY_Qnil
@ RUBY_Qnil
Definition special_consts.h:90
RUBY_Qundef
@ RUBY_Qundef
Represents so-called undef.
Definition special_consts.h:91
RUBY_Qfalse
@ RUBY_Qfalse
Definition special_consts.h:88
RB_FLONUM_P
static bool RB_FLONUM_P(VALUE obj)
Checks if the given object is a so-called Flonum.
Definition special_consts.h:288
stdbool.h
C99 shim for <stdbool.h>
value.h
Defines VALUE and ID.
VALUE
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
rb_type
static enum ruby_value_type rb_type(VALUE obj)
Identical to RB_BUILTIN_TYPE(), except it can also accept special constants.
Definition value_type.h:225
RB_BUILTIN_TYPE
static enum ruby_value_type RB_BUILTIN_TYPE(VALUE obj)
Queries the type of the object.
Definition value_type.h:182
RB_FLOAT_TYPE_P
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
Definition value_type.h:264
RB_SYMBOL_P
static bool RB_SYMBOL_P(VALUE obj)
Queries if the object is an instance of rb_cSymbol.
Definition value_type.h:307
Check_Type
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
Definition value_type.h:433
rb_integer_type_p
static bool rb_integer_type_p(VALUE obj)
Queries if the object is an instance of rb_cInteger.
Definition value_type.h:204
RB_DYNAMIC_SYM_P
static bool RB_DYNAMIC_SYM_P(VALUE obj)
Queries if the object is a dynamic symbol.
Definition value_type.h:287
RB_TYPE_P
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition value_type.h:376
ruby_value_type
ruby_value_type
C-level type of an object.
Definition value_type.h:113
RUBY_T_SYMBOL
@ RUBY_T_SYMBOL
Definition value_type.h:135
RUBY_T_MATCH
@ RUBY_T_MATCH
Definition value_type.h:128
RUBY_T_MODULE
@ RUBY_T_MODULE
Definition value_type.h:118
RUBY_T_ICLASS
@ RUBY_T_ICLASS
Hidden classes known as IClasses.
Definition value_type.h:141
RUBY_T_MOVED
@ RUBY_T_MOVED
Definition value_type.h:143
RUBY_T_FIXNUM
@ RUBY_T_FIXNUM
Integers formerly known as Fixnums.
Definition value_type.h:136
RUBY_T_IMEMO
@ RUBY_T_IMEMO
Definition value_type.h:139
RUBY_T_NODE
@ RUBY_T_NODE
Definition value_type.h:140
RUBY_T_OBJECT
@ RUBY_T_OBJECT
Definition value_type.h:116
RUBY_T_DATA
@ RUBY_T_DATA
Definition value_type.h:127
RUBY_T_FALSE
@ RUBY_T_FALSE
Definition value_type.h:134
RUBY_T_UNDEF
@ RUBY_T_UNDEF
Definition value_type.h:137
RUBY_T_COMPLEX
@ RUBY_T_COMPLEX
Definition value_type.h:129
RUBY_T_STRING
@ RUBY_T_STRING
Definition value_type.h:120
RUBY_T_HASH
@ RUBY_T_HASH
Definition value_type.h:123
RUBY_T_NIL
@ RUBY_T_NIL
Definition value_type.h:132
RUBY_T_CLASS
@ RUBY_T_CLASS
Definition value_type.h:117
RUBY_T_ARRAY
@ RUBY_T_ARRAY
Definition value_type.h:122
RUBY_T_MASK
@ RUBY_T_MASK
Bitmask of ruby_value_type.
Definition value_type.h:145
RUBY_T_RATIONAL
@ RUBY_T_RATIONAL
Definition value_type.h:130
RUBY_T_ZOMBIE
@ RUBY_T_ZOMBIE
Definition value_type.h:142
RUBY_T_BIGNUM
@ RUBY_T_BIGNUM
Definition value_type.h:125
RUBY_T_TRUE
@ RUBY_T_TRUE
Definition value_type.h:133
RUBY_T_FLOAT
@ RUBY_T_FLOAT
Definition value_type.h:119
RUBY_T_STRUCT
@ RUBY_T_STRUCT
Definition value_type.h:124
RUBY_T_NONE
@ RUBY_T_NONE
Non-object (swept etc.)
Definition value_type.h:114
RUBY_T_REGEXP
@ RUBY_T_REGEXP
Definition value_type.h:121
RUBY_T_FILE
@ RUBY_T_FILE
Definition value_type.h:126