From 32a8986a1916b672acd6992bd646af0aa409960b Mon Sep 17 00:00:00 2001 From: Yee Cheng Chin Date: Thu, 1 Jan 2026 22:42:53 -0800 Subject: [PATCH] Fix Ruby 4.0 dynamic builds correctly by inlining rb_check_typeddata Ruby 4.0 broke Vim compilation in dynamic builds. That's because the function `rb_check_typeddata` is now used in an inline function defined in Ruby headers, which causes it to link against the lib statically rather than using the one we load in dynamically (`dll_rb_check_typeddata`) as we only remap it later (after the Ruby header include). A previous fix (v9.1.2036) did a wrong fix by stubbing in the actual inline function `rbimpl_check_typeddata` instead. This does not work because the inline function is not part of the dynamic lib and therefore it's not possible to load it in dynamically (the patch also did not actually attempt to load in the stub). With that patch, Vim would crash when this function is used as the function pointer is null. Fix this properly by reverting the previous change, and simply stub `rb_check_typeddata` using similar mechanisms the file had already set up for similar situations. Fix #18884 --- src/if_ruby.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/if_ruby.c b/src/if_ruby.c index 49fdc34dd5316b..913936174a5e01 100644 --- a/src/if_ruby.c +++ b/src/if_ruby.c @@ -73,6 +73,11 @@ # define rb_num2int rb_num2int_stub # endif +# if RUBY_VERSION >= 20 +// USE_TYPEDDATA is not defined yet. We just check for 2.0. +# define rb_check_typeddata rb_check_typeddata_stub +#endif + # if RUBY_VERSION == 21 // Ruby 2.1 adds new GC called RGenGC and RARRAY_PTR uses // rb_gc_writebarrier_unprotect_promoted if USE_RGENGC @@ -243,12 +248,6 @@ static int ruby_convert_to_vim_value(VALUE val, typval_T *rettv); # if RUBY_VERSION < 30 # define rb_check_type dll_rb_check_type # endif -# ifdef USE_TYPEDDATA -# if RUBY_VERSION >= 40 -# define rbimpl_check_typeddata dll_rbimpl_check_typeddata -# endif -# define rb_check_typeddata dll_rb_check_typeddata -# endif # define rb_class_path dll_rb_class_path # ifdef USE_TYPEDDATA # if RUBY_VERSION >= 23 @@ -376,9 +375,6 @@ VALUE *dll_rb_cTrueClass; static VALUE (*dll_rb_class_new_instance) (int,VALUE*,VALUE); static void (*dll_rb_check_type) (VALUE,int); # ifdef USE_TYPEDDATA -# if RUBY_VERSION >= 40 -static void *(*dll_rbimpl_check_typeddata) (VALUE,const rb_data_type_t *); -# endif static void *(*dll_rb_check_typeddata) (VALUE,const rb_data_type_t *); # endif static VALUE (*dll_rb_class_path) (VALUE); @@ -607,6 +603,12 @@ rb_unexpected_type_stub(VALUE self, int t) dll_rb_unexpected_type(self, t); } # endif +# ifdef USE_TYPEDDATA +void *rb_check_typeddata_stub(VALUE obj, const rb_data_type_t *data_type) +{ + return dll_rb_check_typeddata(obj, data_type); +} +# endif # endif // ifndef PROTO static HINSTANCE hinstRuby = NULL; // Instance of ruby.dll