From 1b8d4a3b8b2b5bc2ffd5637070da28ead2d7f1d9 Mon Sep 17 00:00:00 2001 From: Ufuk Kayserilioglu Date: Thu, 26 Mar 2026 01:14:11 +0200 Subject: [PATCH] Constants defined in C extensions might be attributed other the gems Some constants like `ERB::Escape` that are defind in C extension components of gems are currently failing the `defined_in_gem?` look up. This happens for `ERB::Escape` because, instead of `erb/lib/erb/utils.rb` loading the shared-object for `escape`, we have `erubi` loading it. Thus, when we do the backtrace scan to find the file that is loading the constant we attribute it to the `erubi` gem. This is because there are no frames in the backtrace for the class definition coming from a C extension, thus we miss the actual file that does the `ERB::Escape` definition. Since we can look up the source location of constants now, it makes more sense to include that in the list of file candidate locations. Which makes it resilient against these kinds of mistakes. --- lib/tapioca/runtime/reflection.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/tapioca/runtime/reflection.rb b/lib/tapioca/runtime/reflection.rb index 788a418c7..3a0752a6e 100644 --- a/lib/tapioca/runtime/reflection.rb +++ b/lib/tapioca/runtime/reflection.rb @@ -213,9 +213,16 @@ def resolve_loc(locations) #: (T::Module[top] constant) -> Set[String] def file_candidates_for(constant) - relevant_methods_for(constant).filter_map do |method| + # Grab all source files for (relevant) methods defined on the constant + candidates = relevant_methods_for(constant).filter_map do |method| method.source_location&.first end.to_set + + # Add the source file for the constant definition itself, if available. + source_location_candidate = const_source_location(name_of(constant).to_s)&.file + candidates.add(source_location_candidate) if source_location_candidate + + candidates end #: (T::Module[top] constant) -> untyped