From 89e81e91302c2d955607af2f6a205aa7a7d28004 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 11 May 2026 08:13:51 +0900 Subject: [PATCH] limitations.md: document absence of implicit type conversion Add a section explaining that mruby intentionally does not consult to_int/to_str/to_ary/to_hash for implicit type coercion in built-in operations, even though identity versions remain defined on the corresponding built-in types. Note that Float#to_int and Array#to_ary are not defined, and contrast with explicit conversion methods (to_i, to_s, to_a) which do work. ref #2979 Co-authored-by: Claude --- doc/limitations.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/doc/limitations.md b/doc/limitations.md index 5d7a3181f..6470f65a2 100644 --- a/doc/limitations.md +++ b/doc/limitations.md @@ -290,3 +290,48 @@ arbitrary-precision integers when included. (included in the `stdlib` gembox). Even with the gem, `ObjectSpace.each_object` has limited functionality compared to CRuby. + +## No Implicit Type Conversion (`to_int`, `to_str`, `to_ary`, ...) + +mruby does not perform implicit type conversion through methods +like `to_int`, `to_str`, `to_ary`, or `to_hash`. CRuby uses these +to let user-defined classes duck-type as built-in types — for +example `Array#[]` calls `to_int` on its argument, `String#+` calls +`to_str`, and multiple assignment calls `to_ary` on its right-hand +side. mruby's built-in operations require the actual built-in type +and do not consult these conversion methods. + +```ruby +class MyInt; def to_int; 42; end; end +class MyStr; def to_str; "x"; end; end +class MyAry; def to_ary; [1,2,3]; end; end +``` + +#### CRuby + +``` +[1,2,3][MyInt.new] # => nil (to_int called -> ary[42]) +"a" + MyStr.new # => "ax" (to_str called) +a, b, c = MyAry.new # => a=1, b=2, c=3 (to_ary called) +``` + +#### mruby + +``` +[1,2,3][MyInt.new] # TypeError +"a" + MyStr.new # TypeError +a, b, c = MyAry.new # a=, b=nil, c=nil (treated as single value) +``` + +Identity versions of `to_int`, `to_str`, `to_sym`, and `to_hash` +remain defined on the corresponding built-in types so that +`respond_to?(:to_str)`-style checks work for built-in instances. +`Float#to_int` and `Array#to_ary` are intentionally not defined. + +Explicit conversion methods (`to_i`, `to_s`, `to_a`) work as in +CRuby and are called by features such as string interpolation and +the splat operator (`*obj`). + +This is a deliberate trade-off: implicit conversion forces every +coercion site to go through method dispatch and can silently mask +type-mismatch bugs.