# New Ticket Created by   
# Please include the string:  [perl #129844]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org/Ticket/Display.html?id=129844 >



We can use a literal numeral or an Int with a sub that takes a native:

<Zoffix> m: sub foo (int) { say "OK!" }; foo 2
<camelia> rakudo-moar d03459: OUTPUT«OK!␤»
<Zoffix> m: sub foo (int) { say "OK!" }; my Int $x = 2; foo $x
<camelia> rakudo-moar d03459: OUTPUT«OK!␤»

But, such auto-unboxing doesn't work if we use a multi instead:

<Zoffix> m: multi foo (int) { say "OK!" }; foo 2
<camelia> rakudo-moar d03459: OUTPUT«Cannot resolve caller foo(Int);  
none of these signatures match:␤    (int)␤  in block <unit> at <tmp>  
line 1␤␤»
<Zoffix> m: multi foo (int) { say "OK!" }; my Int $x = 2; foo $x
<camelia> rakudo-moar d03459: OUTPUT«Cannot resolve caller foo(Int);  
none of these signatures match:␤    (int)␤  in block <unit> at <tmp>  
line 1␤␤»

Even though auto-boxing for natives works regardless of whether we  
have a multi:

<Zoffix> m: sub foo (Int) { say "OK!" }; my int $x = 2; foo $x
<camelia> rakudo-moar d03459: OUTPUT«OK!␤»
<Zoffix> m: multi foo (Int) { say "OK!" }; my int $x = 2; foo $x
<camelia> rakudo-moar d03459: OUTPUT«OK!␤»

I found this bug while out on a hunt for another one, and it looks  
like the solutions might be very similar, so I'm filing this with a  
tentative "leave it with me."

As part of this issue and the one I'm resolving, I had to write out a  
list of rules of how literals, natives, and their related types behave  
in multi resolution:

     (I describe int/Int, but same applies for other natives that have  
a boxed Perl 6 equivalent):

     0) Literal: treat as Int
     1) Int:
         1.1) Use as Int, if have candidate
         1.2) Use as native, if:
             1.2.1) have native candidate
             1.2.2) size fits
     2) Native:
         2.1) Use as native, if have candidate
         2.2) Use as Int, if have candidate
     And so we have:

         my int $i = 2; # used in all examples to indicate native int

         multi foo (int $x) {say "native" };
         foo 2; # native; 0 => 1 => 1.2

         multi foo (Int $x) {say "other Int" };
         foo 2; # other Int; 0 => 1 => 1.1

         multi foo (int $x) {say "native" };
         foo $i; # native; 2 => 2.1

         multi foo (Int $x) {say "other Int" };
         foo $i; # other Int; 2 => 2.2

         multi foo (int $x) {say "native"    };
         multi foo (Int $x) {say "other Int" };
         foo  2; # other Int; 0 => 1 => 1.1
         foo $i; # native; 2 => 2.1

         multi foo (int $x) {say "native"    };
         multi foo (Str $x) {say "other Str" };
         foo  2; # native; 0 => 1 => 1.2
         foo $i; # native; 2 => 2.1

         multi foo (Int $x) {say "other Int" };
         multi foo (Str $x) {say "other Str" };
         foo  2; # other Int; 0 => 1 => 1.1
         foo $i; # other Int; 2 => 2.2

         multi foo (int $x) {say "native"    };
         multi foo (Int $x) {say "other Int" };
         foo 2;      # other Int; 0 => 1 => 1.1
         foo 2**100; # other Int; 0 => 1 => 1.1

         multi foo (int $x) {say "native" };
         foo 2;      # native; 0 => 1.2
         foo 2**100; # X::Multi::NoMatch (no Int candidate);
         # 0 => 1 => 1.2 => 1.2.2 (fails to match at this point)

         multi foo (int $x, int $y) {say "native"       };
         multi foo (Int $x, Int $y) {say "other Int"    };
         foo  2, $i; # other Int; (0 => 1 => 1.1), (2 => 2.1)
         foo  2, 2;  # other Int; (0 => 1 => 1.1), (0 => 1 => 1.1)
         foo $i, $i; # native; (2 => 2.1), (2 => 2.1)

         multi foo (int $x, int $y) {say "native"       };
         multi foo (Int $x, int $y) {say "Int + native" };
         multi foo (Int $x, Int $y) {say "other Int"    };
         foo  2, $i; # Int + native; (0 => 1 => 1.1), (2 => 2.1)
         foo  2, 2;  # other Int; (0 => 1 => 1.1), (0 => 1 => 1.1)
         foo $i, $i; # native; (2 => 2.1), (2 => 2.1)



Reply via email to