Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check_Type errors #4741

Merged
merged 4 commits into from Aug 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 14 additions & 6 deletions error.c
Expand Up @@ -909,9 +909,9 @@ static const char builtin_types[][10] = {
"", /* 0x17 */
"", /* 0x18 */
"", /* 0x19 */
"Memo", /* internal use: general memo */
"Node", /* internal use: syntax tree node */
"iClass", /* internal use: mixed-in module holder */
"<Memo>", /* internal use: general memo */
"<Node>", /* internal use: syntax tree node */
"<iClass>", /* internal use: mixed-in module holder */
};

const char *
Expand Down Expand Up @@ -972,7 +972,7 @@ rb_builtin_class_name(VALUE x)
return etype;
}

NORETURN(static void unexpected_type(VALUE, int, int));
COLDFUNC NORETURN(static void unexpected_type(VALUE, int, int));
#define UNDEF_LEAKED "undef leaked to the Ruby space"

static void
Expand Down Expand Up @@ -1001,20 +1001,28 @@ rb_check_type(VALUE x, int t)
{
int xt;

if (x == Qundef) {
if (RB_UNLIKELY(x == Qundef)) {
rb_bug(UNDEF_LEAKED);
}

xt = TYPE(x);
if (xt != t || (xt == T_DATA && RTYPEDDATA_P(x))) {
/*
* Typed data is not simple `T_DATA`, but in a sense an
* extension of `struct RVALUE`, which are incompatible with
* each other except when inherited.
*
* So it is not enough to just check `T_DATA`, it must be
* identified by its `type` using `Check_TypedStruct` instead.
*/
unexpected_type(x, xt, t);
}
}

void
rb_unexpected_type(VALUE x, int t)
{
if (x == Qundef) {
if (RB_UNLIKELY(x == Qundef)) {
rb_bug(UNDEF_LEAKED);
}

Expand Down
20 changes: 6 additions & 14 deletions include/ruby/internal/value_type.h
Expand Up @@ -337,25 +337,17 @@ static inline void
Check_Type(VALUE v, enum ruby_value_type t)
{
if (RB_UNLIKELY(! RB_TYPE_P(v, t))) {
goto slowpath;
goto unexpected_type;
}
else if (t != RUBY_T_DATA) {
goto fastpath;
}
else if (rbimpl_rtypeddata_p(v)) {
/* The intention itself is not necessarily clear to me, but at least it
* is intentional to rule out typed data here. See commit
* a7c32bf81d3391cfb78cfda278f469717d0fb794. */
goto slowpath;
else if (t == RUBY_T_DATA && rbimpl_rtypeddata_p(v)) {
/* Typed data is not simple `T_DATA`, see `rb_check_type` */
goto unexpected_type;
}
else {
goto fastpath;
return;
}

fastpath:
return;

slowpath: /* <- :TODO: mark this label as cold. */
unexpected_type:
rb_unexpected_type(v, t);
}

Expand Down