icy-arctic-fox / spectator

Feature-rich testing framework for Crystal inspired by RSpec.
https://gitlab.com/arctic-fox/spectator
MIT License
101 stars 4 forks source link

Mocks fail to compile for methods with free variables #48

Closed postmodern closed 1 year ago

postmodern commented 1 year ago

I was trying to test chars.cr against Crystal 1.6.2 and Spectator 0.11.4, but got this strange error coming from deep within enumerable.cr. The beginning of the error is a macro expansion of a method stub. I assume I need to update how I'm defining the stubs?

    mock Chars::CharSet do
      stub :|, other : Chars::CharSet
    end

    let(other) { described_class.new }
    let(return_value) { described_class.new }

    it "must call #+" do
      expect(subject).to receive(:|).with(other).and_return(return_value)

      expect(subject + other).to be(return_value)
    end

Error Trace

$ crystal spec --error-trace 
There was a problem expanding macro 'finished'

Called macro defined in macro 'define_subtype'

 46 | macro finished

Which expanded to:

 > 1 |             stub_type Chars::CharSet
 > 2 | 
 > 3 |             stub(:|, other : Chars::CharSet)
 > 4 |           
Error: expanding macro

There was a problem expanding macro 'stub_type'

Called macro defined in lib/spectator/src/spectator/mocks/stubbable.cr:339:13

 339 | private macro stub_type(type_name = @type)

Which expanded to:

 >    1 |       
 >    2 |       
 >    3 |         
 >    4 |           default_stub  def colorize(
 >    5 |             r : UInt8, g : UInt8, b : UInt8, 
 >    6 |             
 >    7 |             
 >    8 |           )
 >    9 |             super
 >   10 |           end
 >   11 |         
 >   12 |           default_stub  def colorize(
 >   13 |             fore : UInt8, 
 >   14 |             
 >   15 |             
 >   16 |           )
 >   17 |             super
 >   18 |           end
 >   19 |         
 >   20 |           default_stub  def colorize(
 >   21 |             fore : Symbol, 
 >   22 |             
 >   23 |             
 >   24 |           )
 >   25 |             super
 >   26 |           end
 >   27 |         
 >   28 |           default_stub  def colorize(
 >   29 |             fore : Color, 
 >   30 |             
 >   31 |             
 >   32 |           )
 >   33 |             super
 >   34 |           end
 >   35 |         
 >   36 |           default_stub  def colorize(
 >   37 |             
 >   38 |             
 >   39 |             
 >   40 |           ) : Colorize::Object
 >   41 |             super
 >   42 |           end
 >   43 |         
 >   44 | 
 >   45 |         
 >   46 |       
 >   47 |         
 >   48 |           abstract_stub  def ==(
 >   49 |             other, 
 >   50 |             
 >   51 |             
 >   52 |           )
 >   53 |             super
 >   54 |           end
 >   55 |         
 >   56 |           default_stub  def !=(
 >   57 |             other, 
 >   58 |             
 >   59 |             
 >   60 |           )
 >   61 |             super
 >   62 |           end
 >   63 |         
 >   64 |           default_stub  def !~(
 >   65 |             other, 
 >   66 |             
 >   67 |             
 >   68 |           )
 >   69 |             super
 >   70 |           end
 >   71 |         
 >   72 |           default_stub  def ===(
 >   73 |             other : JSON::Any, 
 >   74 |             
 >   75 |             
 >   76 |           )
 >   77 |             super
 >   78 |           end
 >   79 |         
 >   80 |           default_stub  def ===(
 >   81 |             other, 
 >   82 |             
 >   83 |             
 >   84 |           )
 >   85 |             super
 >   86 |           end
 >   87 |         
 >   88 |           default_stub  def =~(
 >   89 |             other, 
 >   90 |             
 >   91 |             
 >   92 |           )
 >   93 |             super
 >   94 |           end
 >   95 |         
 >   96 |           abstract_stub  def hash(
 >   97 |             hasher, 
 >   98 |             
 >   99 |             
 >  100 |           )
 >  101 |             super
 >  102 |           end
 >  103 |         
 >  104 |           default_stub  def hash(
 >  105 |             
 >  106 |             
 >  107 |             
 >  108 |           )
 >  109 |             super
 >  110 |           end
 >  111 |         
 >  112 |           abstract_stub  def to_s(
 >  113 |             io : IO, 
 >  114 |             
 >  115 |             
 >  116 |           ) : Nil
 >  117 |             super
 >  118 |           end
 >  119 |         
 >  120 |           default_stub  def to_s(
 >  121 |             
 >  122 |             
 >  123 |             
 >  124 |           ) : String
 >  125 |             super
 >  126 |           end
 >  127 |         
 >  128 |           default_stub  def inspect(
 >  129 |             io : IO, 
 >  130 |             
 >  131 |             
 >  132 |           ) : Nil
 >  133 |             super
 >  134 |           end
 >  135 |         
 >  136 |           default_stub  def inspect(
 >  137 |             
 >  138 |             
 >  139 |             
 >  140 |           ) : String
 >  141 |             super
 >  142 |           end
 >  143 |         
 >  144 |           default_stub  def pretty_print(
 >  145 |             pp : PrettyPrint, 
 >  146 |             
 >  147 |             
 >  148 |           ) : Nil
 >  149 |             super
 >  150 |           end
 >  151 |         
 >  152 |           default_stub  def pretty_inspect(
 >  153 |             width = 79, newline = "\n", indent = 0, 
 >  154 |             
 >  155 |             
 >  156 |           ) : String
 >  157 |             super
 >  158 |           end
 >  159 |         
 >  160 |           default_stub  def tap(
 >  161 |             
 >  162 |             
 >  163 |             &
 >  164 |           )
 >  165 |             super { |*__temp_1063| yield *__temp_1063 }
 >  166 |           end
 >  167 |         
 >  168 |           default_stub  def try(
 >  169 |             
 >  170 |             
 >  171 |             &
 >  172 |           )
 >  173 |             super { |*__temp_1063| yield *__temp_1063 }
 >  174 |           end
 >  175 |         
 >  176 |           default_stub  def in?(
 >  177 |             collection : Object, 
 >  178 |             
 >  179 |             
 >  180 |           ) : Bool
 >  181 |             super
 >  182 |           end
 >  183 |         
 >  184 |           default_stub  def in?(
 >  185 |             *values : Object, 
 >  186 |             
 >  187 |             
 >  188 |           ) : Bool
 >  189 |             super
 >  190 |           end
 >  191 |         
 >  192 |           default_stub  def not_nil!(
 >  193 |             
 >  194 |             
 >  195 |             
 >  196 |           )
 >  197 |             super
 >  198 |           end
 >  199 |         
 >  200 |           default_stub  def itself(
 >  201 |             
 >  202 |             
 >  203 |             
 >  204 |           )
 >  205 |             super
 >  206 |           end
 >  207 |         
 >  208 |           abstract_stub  def dup(
 >  209 |             
 >  210 |             
 >  211 |             
 >  212 |           )
 >  213 |             super
 >  214 |           end
 >  215 |         
 >  216 |           default_stub  def unsafe_as(
 >  217 |             type : T.class, 
 >  218 |             
 >  219 |             
 >  220 |           ) forall T
 >  221 |             super
 >  222 |           end
 >  223 |         
 >  224 |           default_stub  def crystal_type_id(
 >  225 |             
 >  226 |             
 >  227 |             
 >  228 |           ) : Int32
 >  229 |             super
 >  230 |           end
 >  231 |         
 >  232 |           default_stub  def to_json(
 >  233 |             io : IO, 
 >  234 |             
 >  235 |             
 >  236 |           ) : Nil
 >  237 |             super
 >  238 |           end
 >  239 |         
 >  240 |           default_stub  def to_json(
 >  241 |             
 >  242 |             
 >  243 |             
 >  244 |           ) : String
 >  245 |             super
 >  246 |           end
 >  247 |         
 >  248 |           default_stub  def to_pretty_json(
 >  249 |             indent : String = "  ", 
 >  250 |             
 >  251 |             
 >  252 |           ) : String
 >  253 |             super
 >  254 |           end
 >  255 |         
 >  256 |           default_stub  def to_pretty_json(
 >  257 |             io : IO, indent : String = "  ", 
 >  258 |             
 >  259 |             
 >  260 |           ) : Nil
 >  261 |             super
 >  262 |           end
 >  263 |         
 >  264 | 
 >  265 |         
 >  266 |           default_stub protected def self.set_crystal_type_id(
 >  267 |             ptr, 
 >  268 |             
 >  269 |             
 >  270 |           )
 >  271 |             super
 >  272 |           end
 >  273 |         
 >  274 |           default_stub  def self.from_json(
 >  275 |             string_or_io, root : String, 
 >  276 |             
 >  277 |             
 >  278 |           )
 >  279 |             super
 >  280 |           end
 >  281 |         
 >  282 |           default_stub  def self.from_json(
 >  283 |             string_or_io, 
 >  284 |             
 >  285 |             
 >  286 |           )
 >  287 |             super
 >  288 |           end
 >  289 |         
 >  290 |       
 >  291 |         
 >  292 |           default_stub  def object_id(
 >  293 |             
 >  294 |             
 >  295 |             
 >  296 |           ) : UInt64
 >  297 |             super
 >  298 |           end
 >  299 |         
 >  300 |           default_stub  def ==(
 >  301 |             other : self, 
 >  302 |             
 >  303 |             
 >  304 |           )
 >  305 |             super
 >  306 |           end
 >  307 |         
 >  308 |           default_stub  def ==(
 >  309 |             other : JSON::Any, 
 >  310 |             
 >  311 |             
 >  312 |           )
 >  313 |             super
 >  314 |           end
 >  315 |         
 >  316 |           default_stub  def ==(
 >  317 |             other, 
 >  318 |             
 >  319 |             
 >  320 |           )
 >  321 |             super
 >  322 |           end
 >  323 |         
 >  324 |           default_stub  def same?(
 >  325 |             other : Reference, 
 >  326 |             
 >  327 |             
 >  328 |           ) : Bool
 >  329 |             super
 >  330 |           end
 >  331 |         
 >  332 |           default_stub  def same?(
 >  333 |             other : Nil, 
 >  334 |             
 >  335 |             
 >  336 |           )
 >  337 |             super
 >  338 |           end
 >  339 |         
 >  340 |           default_stub  def dup(
 >  341 |             
 >  342 |             
 >  343 |             
 >  344 |           )
 >  345 |             super
 >  346 |           end
 >  347 |         
 >  348 |           default_stub  def hash(
 >  349 |             hasher, 
 >  350 |             
 >  351 |             
 >  352 |           )
 >  353 |             super
 >  354 |           end
 >  355 |         
 >  356 |           default_stub  def inspect(
 >  357 |             io : IO, 
 >  358 |             
 >  359 |             
 >  360 |           ) : Nil
 >  361 |             super
 >  362 |           end
 >  363 |         
 >  364 |           default_stub  def pretty_print(
 >  365 |             pp, 
 >  366 |             
 >  367 |             
 >  368 |           ) : Nil
 >  369 |             super
 >  370 |           end
 >  371 |         
 >  372 |           default_stub  def to_s(
 >  373 |             io : IO, 
 >  374 |             
 >  375 |             
 >  376 |           ) : Nil
 >  377 |             super
 >  378 |           end
 >  379 |         
 >  380 |           default_stub private def exec_recursive(
 >  381 |             method, 
 >  382 |             
 >  383 |             &
 >  384 |           )
 >  385 |             super { |*__temp_1063| yield *__temp_1063 }
 >  386 |           end
 >  387 |         
 >  388 |           default_stub private def exec_recursive_clone(
 >  389 |             
 >  390 |             
 >  391 |             &
 >  392 |           )
 >  393 |             super { |*__temp_1063| yield *__temp_1063 }
 >  394 |           end
 >  395 |         
 >  396 | 
 >  397 |         
 >  398 |       
 >  399 |         
 >  400 |           abstract_stub  def each(
 >  401 |             
 >  402 |             
 >  403 |             & : (T ->)
 >  404 |           )
 >  405 |             super { |*__temp_1063| yield *__temp_1063 }
 >  406 |           end
 >  407 |         
 >  408 |           default_stub  def all?(
 >  409 |             
 >  410 |             
 >  411 |             & : (T ->)
 >  412 |           ) : Bool
 >  413 |             super { |*__temp_1063| yield *__temp_1063 }
 >  414 |           end
 >  415 |         
 >  416 |           default_stub  def all?(
 >  417 |             pattern, 
 >  418 |             
 >  419 |             
 >  420 |           ) : Bool
 >  421 |             super
 >  422 |           end
 >  423 |         
 >  424 |           default_stub  def all?(
 >  425 |             
 >  426 |             
 >  427 |             
 >  428 |           ) : Bool
 >  429 |             super
 >  430 |           end
 >  431 |         
 >  432 |           default_stub  def any?(
 >  433 |             
 >  434 |             
 >  435 |             & : (T ->)
 >  436 |           ) : Bool
 >  437 |             super { |*__temp_1063| yield *__temp_1063 }
 >  438 |           end
 >  439 |         
 >  440 |           default_stub  def any?(
 >  441 |             pattern, 
 >  442 |             
 >  443 |             
 >  444 |           ) : Bool
 >  445 |             super
 >  446 |           end
 >  447 |         
 >  448 |           default_stub  def any?(
 >  449 |             
 >  450 |             
 >  451 |             
 >  452 |           ) : Bool
 >  453 |             super
 >  454 |           end
 >  455 |         
 >  456 |           default_stub  def chunks(
 >  457 |             
 >  458 |             
 >  459 |             &block : (T -> U)
 >  460 |           ) forall U
 >  461 |             super { |*__temp_1063| yield *__temp_1063 }
 >  462 |           end
 >  463 |         
 >  464 |           default_stub private def chunks_internal(
 >  465 |             original_block : (T -> U), 
 >  466 |             
 >  467 |             &
 >  468 |           ) forall U
 >  469 |             super { |*__temp_1063| yield *__temp_1063 }
 >  470 |           end
 >  471 |         
 >  472 |           default_stub  def compact_map(
 >  473 |             
 >  474 |             
 >  475 |             & : (T -> _)
 >  476 |           )
 >  477 |             super { |*__temp_1063| yield *__temp_1063 }
 >  478 |           end
 >  479 |         
 >  480 |           default_stub  def count(
 >  481 |             
 >  482 |             
 >  483 |             & : (T ->)
 >  484 |           ) : Int32
 >  485 |             super { |*__temp_1063| yield *__temp_1063 }
 >  486 |           end
 >  487 |         
 >  488 |           default_stub  def count(
 >  489 |             item, 
 >  490 |             
 >  491 |             
 >  492 |           ) : Int32
 >  493 |             super
 >  494 |           end
 >  495 |         
 >  496 |           default_stub  def cycle(
 >  497 |             n, 
 >  498 |             
 >  499 |             & : (T ->)
 >  500 |           ) : Nil
 >  501 |             super { |*__temp_1063| yield *__temp_1063 }
 >  502 |           end
 >  503 |         
 >  504 |           default_stub  def cycle(
 >  505 |             
 >  506 |             
 >  507 |             & : (T ->)
 >  508 |           ) : Nil
 >  509 |             super { |*__temp_1063| yield *__temp_1063 }
 >  510 |           end
 >  511 |         
 >  512 |           default_stub  def each_cons(
 >  513 |             count : Int, reuse = false, 
 >  514 |             
 >  515 |             &
 >  516 |           )
 >  517 |             super { |*__temp_1063| yield *__temp_1063 }
 >  518 |           end
 >  519 |         
 >  520 |           default_stub private def each_cons_internal(
 >  521 |             count : Int, reuse, cons, 
 >  522 |             
 >  523 |             &
 >  524 |           )
 >  525 |             super { |*__temp_1063| yield *__temp_1063 }
 >  526 |           end
 >  527 |         
 >  528 |           default_stub  def each_cons_pair(
 >  529 |             
 >  530 |             
 >  531 |             & : (T, T ->)
 >  532 |           ) : Nil
 >  533 |             super { |*__temp_1063| yield *__temp_1063 }
 >  534 |           end
 >  535 |         
 >  536 |           default_stub  def each_slice(
 >  537 |             count : Int, reuse = false, 
 >  538 |             
 >  539 |             &
 >  540 |           )
 >  541 |             super { |*__temp_1063| yield *__temp_1063 }
 >  542 |           end
 >  543 |         
 >  544 |           default_stub private def each_slice_internal(
 >  545 |             count : Int, type, reuse, 
 >  546 |             
 >  547 |             &
 >  548 |           )
 >  549 |             super { |*__temp_1063| yield *__temp_1063 }
 >  550 |           end
 >  551 |         
 >  552 |           default_stub  def each_with_index(
 >  553 |             offset = 0, 
 >  554 |             
 >  555 |             &
 >  556 |           )
 >  557 |             super { |*__temp_1063| yield *__temp_1063 }
 >  558 |           end
 >  559 |         
 >  560 |           default_stub  def each_with_object(
 >  561 |             obj : U, 
 >  562 |             
 >  563 |             & : (T, U ->)
 >  564 |           ) : U forall U
 >  565 |             super { |*__temp_1063| yield *__temp_1063 }
 >  566 |           end
 >  567 |         
 >  568 |           default_stub  def find(
 >  569 |             if_none = nil, 
 >  570 |             
 >  571 |             & : (T ->)
 >  572 |           )
 >  573 |             super { |*__temp_1063| yield *__temp_1063 }
 >  574 |           end
 >  575 |         
 >  576 |           default_stub  def find!(
 >  577 |             
 >  578 |             
 >  579 |             & : (T ->)
 >  580 |           ) : T
 >  581 |             super { |*__temp_1063| yield *__temp_1063 }
 >  582 |           end
 >  583 |         
 >  584 |           default_stub  def first(
 >  585 |             
 >  586 |             
 >  587 |             &
 >  588 |           )
 >  589 |             super { |*__temp_1063| yield *__temp_1063 }
 >  590 |           end
 >  591 |         
 >  592 |           default_stub  def first(
 >  593 |             count : Int, 
 >  594 |             
 >  595 |             
 >  596 |           ) : Array(T)
 >  597 |             super
 >  598 |           end
 >  599 |         
 >  600 |           default_stub  def first(
 >  601 |             
 >  602 |             
 >  603 |             
 >  604 |           ) : T
 >  605 |             super
 >  606 |           end
 >  607 |         
 >  608 |           default_stub  def first?(
 >  609 |             
 >  610 |             
 >  611 |             
 >  612 |           ) : T | ::Nil
 >  613 |             super
 >  614 |           end
 >  615 |         
 >  616 |           default_stub  def flat_map(
 >  617 |             
 >  618 |             
 >  619 |             & : (T -> _)
 >  620 |           )
 >  621 |             super { |*__temp_1063| yield *__temp_1063 }
 >  622 |           end
 >  623 |         
 >  624 |           default_stub private def flat_map_type(
 >  625 |             elem, 
 >  626 |             
 >  627 |             
 >  628 |           )
 >  629 |             super
 >  630 |           end
 >  631 |         
 >  632 |           default_stub  def group_by(
 >  633 |             
 >  634 |             
 >  635 |             & : (T -> U)
 >  636 |           ) forall U
 >  637 |             super { |*__temp_1063| yield *__temp_1063 }
 >  638 |           end
 >  639 |         
 >  640 |           default_stub  def in_groups_of(
 >  641 |             size : Int, filled_up_with : U = nil, 
 >  642 |             
 >  643 |             
 >  644 |           ) forall U
 >  645 |             super
 >  646 |           end
 >  647 |         
 >  648 |           default_stub  def in_groups_of(
 >  649 |             size : Int, filled_up_with : U = nil, reuse = false, 
 >  650 |             
 >  651 |             &
 >  652 |           ) forall U
 >  653 |             super { |*__temp_1063| yield *__temp_1063 }
 >  654 |           end
 >  655 |         
 >  656 |           default_stub  def includes?(
 >  657 |             obj, 
 >  658 |             
 >  659 |             
 >  660 |           ) : Bool
 >  661 |             super
 >  662 |           end
 >  663 |         
 >  664 |           default_stub  def index(
 >  665 |             
 >  666 |             
 >  667 |             & : (T ->)
 >  668 |           ) : Int32 | ::Nil
 >  669 |             super { |*__temp_1063| yield *__temp_1063 }
 >  670 |           end
 >  671 |         
 >  672 |           default_stub  def index(
 >  673 |             obj, 
 >  674 |             
 >  675 |             
 >  676 |           ) : Int32 | ::Nil
 >  677 |             super
 >  678 |           end
 >  679 |         
 >  680 |           default_stub  def index!(
 >  681 |             
 >  682 |             
 >  683 |             & : (T ->)
 >  684 |           ) : Int32
 >  685 |             super { |*__temp_1063| yield *__temp_1063 }
 >  686 |           end
 >  687 |         
 >  688 |           default_stub  def index!(
 >  689 |             obj, 
 >  690 |             
 >  691 |             
 >  692 |           ) : Int32
 >  693 |             super
 >  694 |           end
 >  695 |         
 >  696 |           default_stub  def index_by(
 >  697 |             
 >  698 |             
 >  699 |             & : (T -> U)
 >  700 |           ) : Hash(U, T) forall U
 >  701 |             super { |*__temp_1063| yield *__temp_1063 }
 >  702 |           end
 >  703 |         
 >  704 |           default_stub  def reduce(
 >  705 |             memo, 
 >  706 |             
 >  707 |             &
 >  708 |           )
 >  709 |             super { |*__temp_1063| yield *__temp_1063 }
 >  710 |           end
 >  711 |         
 >  712 |           default_stub  def reduce(
 >  713 |             
 >  714 |             
 >  715 |             &
 >  716 |           )
 >  717 |             super { |*__temp_1063| yield *__temp_1063 }
 >  718 |           end
 >  719 |         
 >  720 |           default_stub  def reduce?(
 >  721 |             
 >  722 |             
 >  723 |             &
 >  724 |           )
 >  725 |             super { |*__temp_1063| yield *__temp_1063 }
 >  726 |           end
 >  727 |         
 >  728 |           default_stub  def accumulate(
 >  729 |             initial : U, 
 >  730 |             
 >  731 |             
 >  732 |           ) : Array(U) forall U
 >  733 |             super
 >  734 |           end
 >  735 |         
 >  736 |           default_stub  def accumulate(
 >  737 |             
 >  738 |             
 >  739 |             
 >  740 |           ) : Array(T)
 >  741 |             super
 >  742 |           end
 >  743 |         
 >  744 |           default_stub  def accumulate(
 >  745 |             initial : U, 
 >  746 |             
 >  747 |             &block : (U, T -> U)
 >  748 |           ) : Array(U) forall U
 >  749 |             super { |*__temp_1063| yield *__temp_1063 }
 >  750 |           end
 >  751 |         
 >  752 |           default_stub  def accumulate(
 >  753 |             
 >  754 |             
 >  755 |             &block : (T, T -> T)
 >  756 |           ) : Array(T)
 >  757 |             super { |*__temp_1063| yield *__temp_1063 }
 >  758 |           end
 >  759 |         
 >  760 |           default_stub  def join(
 >  761 |             io : IO, separator = "", 
 >  762 |             
 >  763 |             
 >  764 |           ) : Nil
 >  765 |             super
 >  766 |           end
 >  767 |         
 >  768 |           default_stub  def join(
 >  769 |             separator, io : IO, 
 >  770 |             
 >  771 |             
 >  772 |           ) : Nil
 >  773 |             super
 >  774 |           end
 >  775 |         
 >  776 |           default_stub  def join(
 >  777 |             separator = "", 
 >  778 |             
 >  779 |             
 >  780 |           ) : String
 >  781 |             super
 >  782 |           end
 >  783 |         
 >  784 |           default_stub  def join(
 >  785 |             io : IO, separator = "", 
 >  786 |             
 >  787 |             & : (T, IO ->)
 >  788 |           )
 >  789 |             super { |*__temp_1063| yield *__temp_1063 }
 >  790 |           end
 >  791 |         
 >  792 |           default_stub  def join(
 >  793 |             separator, io : IO, 
 >  794 |             
 >  795 |             &
 >  796 |           )
 >  797 |             super { |*__temp_1063| yield *__temp_1063 }
 >  798 |           end
 >  799 |         
 >  800 |           default_stub  def join(
 >  801 |             separator = "", 
 >  802 |             
 >  803 |             & : (T ->)
 >  804 |           )
 >  805 |             super { |*__temp_1063| yield *__temp_1063 }
 >  806 |           end
 >  807 |         
 >  808 |           default_stub  def map(
 >  809 |             
 >  810 |             
 >  811 |             & : (T -> U)
 >  812 |           ) : Array(U) forall U
 >  813 |             super { |*__temp_1063| yield *__temp_1063 }
 >  814 |           end
 >  815 |         
 >  816 |           default_stub  def map_with_index(
 >  817 |             offset = 0, 
 >  818 |             
 >  819 |             & : (T, Int32 -> U)
 >  820 |           ) : Array(U) forall U
 >  821 |             super { |*__temp_1063| yield *__temp_1063 }
 >  822 |           end
 >  823 |         
 >  824 |           default_stub  def max(
 >  825 |             
 >  826 |             
 >  827 |             
 >  828 |           ) : T
 >  829 |             super
 >  830 |           end
 >  831 |         
 >  832 |           default_stub  def max?(
 >  833 |             
 >  834 |             
 >  835 |             
 >  836 |           ) : T | ::Nil
 >  837 |             super
 >  838 |           end
 >  839 |         
 >  840 |           default_stub  def max_by(
 >  841 |             
 >  842 |             
 >  843 |             & : (T -> U)
 >  844 |           ) : T forall U
 >  845 |             super { |*__temp_1063| yield *__temp_1063 }
 >  846 |           end
 >  847 |         
 >  848 |           default_stub  def max_by?(
 >  849 |             
 >  850 |             
 >  851 |             & : (T -> U)
 >  852 |           ) : T | ::Nil forall U
 >  853 |             super { |*__temp_1063| yield *__temp_1063 }
 >  854 |           end
 >  855 |         
 >  856 |           default_stub private def max_by_internal(
 >  857 |             
 >  858 |             
 >  859 |             & : (T -> U)
 >  860 |           ) forall U
 >  861 |             super { |*__temp_1063| yield *__temp_1063 }
 >  862 |           end
 >  863 |         
 >  864 |           default_stub  def max_of(
 >  865 |             
 >  866 |             
 >  867 |             & : (T -> U)
 >  868 |           ) : U forall U
 >  869 |             super { |*__temp_1063| yield *__temp_1063 }
 >  870 |           end
 >  871 |         
 >  872 |           default_stub  def max_of?(
 >  873 |             
 >  874 |             
 >  875 |             & : (T -> U)
 >  876 |           ) : U | ::Nil forall U
 >  877 |             super { |*__temp_1063| yield *__temp_1063 }
 >  878 |           end
 >  879 |         
 >  880 |           default_stub private def max_of_internal(
 >  881 |             
 >  882 |             
 >  883 |             & : (T -> U)
 >  884 |           ) forall U
 >  885 |             super { |*__temp_1063| yield *__temp_1063 }
 >  886 |           end
 >  887 |         
 >  888 |           default_stub  def min(
 >  889 |             
 >  890 |             
 >  891 |             
 >  892 |           ) : T
 >  893 |             super
 >  894 |           end
 >  895 |         
 >  896 |           default_stub  def min?(
 >  897 |             
 >  898 |             
 >  899 |             
 >  900 |           ) : T | ::Nil
 >  901 |             super
 >  902 |           end
 >  903 |         
 >  904 |           default_stub  def min_by(
 >  905 |             
 >  906 |             
 >  907 |             & : (T -> U)
 >  908 |           ) : T forall U
 >  909 |             super { |*__temp_1063| yield *__temp_1063 }
 >  910 |           end
 >  911 |         
 >  912 |           default_stub  def min_by?(
 >  913 |             
 >  914 |             
 >  915 |             & : (T -> U)
 >  916 |           ) : T | ::Nil forall U
 >  917 |             super { |*__temp_1063| yield *__temp_1063 }
 >  918 |           end
 >  919 |         
 >  920 |           default_stub private def min_by_internal(
 >  921 |             
 >  922 |             
 >  923 |             & : (T -> U)
 >  924 |           ) forall U
 >  925 |             super { |*__temp_1063| yield *__temp_1063 }
 >  926 |           end
 >  927 |         
 >  928 |           default_stub  def min_of(
 >  929 |             
 >  930 |             
 >  931 |             & : (T -> U)
 >  932 |           ) : U forall U
 >  933 |             super { |*__temp_1063| yield *__temp_1063 }
 >  934 |           end
 >  935 |         
 >  936 |           default_stub  def min_of?(
 >  937 |             
 >  938 |             
 >  939 |             & : (T -> U)
 >  940 |           ) : U | ::Nil forall U
 >  941 |             super { |*__temp_1063| yield *__temp_1063 }
 >  942 |           end
 >  943 |         
 >  944 |           default_stub private def min_of_internal(
 >  945 |             
 >  946 |             
 >  947 |             & : (T -> U)
 >  948 |           ) forall U
 >  949 |             super { |*__temp_1063| yield *__temp_1063 }
 >  950 |           end
 >  951 |         
 >  952 |           default_stub  def minmax(
 >  953 |             
 >  954 |             
 >  955 |             
 >  956 |           ) : ::Tuple(T, T)
 >  957 |             super
 >  958 |           end
 >  959 |         
 >  960 |           default_stub  def minmax?(
 >  961 |             
 >  962 |             
 >  963 |             
 >  964 |           ) : ::Tuple(T | ::Nil, T | ::Nil)
 >  965 |             super
 >  966 |           end
 >  967 |         
 >  968 |           default_stub  def minmax_by(
 >  969 |             
 >  970 |             
 >  971 |             & : (T -> U)
 >  972 |           ) : ::Tuple(T, T) forall U
 >  973 |             super { |*__temp_1063| yield *__temp_1063 }
 >  974 |           end
 >  975 |         
 >  976 |           default_stub  def minmax_by?(
 >  977 |             
 >  978 |             
 >  979 |             & : (T -> U)
 >  980 |           ) : ::Tuple(T, T) | ::Tuple(Nil, Nil) forall U
 >  981 |             super { |*__temp_1063| yield *__temp_1063 }
 >  982 |           end
 >  983 |         
 >  984 |           default_stub private def minmax_by_internal(
 >  985 |             
 >  986 |             
 >  987 |             & : (T -> U)
 >  988 |           ) forall U
 >  989 |             super { |*__temp_1063| yield *__temp_1063 }
 >  990 |           end
 >  991 |         
 >  992 |           default_stub  def minmax_of(
 >  993 |             
 >  994 |             
 >  995 |             & : (T -> U)
 >  996 |           ) : ::Tuple(U, U) forall U
 >  997 |             super { |*__temp_1063| yield *__temp_1063 }
 >  998 |           end
 >  999 |         
 > 1000 |           default_stub  def minmax_of?(
 > 1001 |             
 > 1002 |             
 > 1003 |             & : (T -> U)
 > 1004 |           ) : ::Tuple(U, U) | ::Tuple(Nil, Nil) forall U
 > 1005 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1006 |           end
 > 1007 |         
 > 1008 |           default_stub private def minmax_of_internal(
 > 1009 |             
 > 1010 |             
 > 1011 |             & : (T -> U)
 > 1012 |           ) forall U
 > 1013 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1014 |           end
 > 1015 |         
 > 1016 |           default_stub private def compare_or_raise(
 > 1017 |             value, memo, 
 > 1018 |             
 > 1019 |             
 > 1020 |           )
 > 1021 |             super
 > 1022 |           end
 > 1023 |         
 > 1024 |           default_stub  def none?(
 > 1025 |             
 > 1026 |             
 > 1027 |             & : (T ->)
 > 1028 |           ) : Bool
 > 1029 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1030 |           end
 > 1031 |         
 > 1032 |           default_stub  def none?(
 > 1033 |             pattern, 
 > 1034 |             
 > 1035 |             
 > 1036 |           ) : Bool
 > 1037 |             super
 > 1038 |           end
 > 1039 |         
 > 1040 |           default_stub  def none?(
 > 1041 |             
 > 1042 |             
 > 1043 |             
 > 1044 |           ) : Bool
 > 1045 |             super
 > 1046 |           end
 > 1047 |         
 > 1048 |           default_stub  def one?(
 > 1049 |             
 > 1050 |             
 > 1051 |             & : (T ->)
 > 1052 |           ) : Bool
 > 1053 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1054 |           end
 > 1055 |         
 > 1056 |           default_stub  def one?(
 > 1057 |             pattern, 
 > 1058 |             
 > 1059 |             
 > 1060 |           ) : Bool
 > 1061 |             super
 > 1062 |           end
 > 1063 |         
 > 1064 |           default_stub  def one?(
 > 1065 |             
 > 1066 |             
 > 1067 |             
 > 1068 |           ) : Bool
 > 1069 |             super
 > 1070 |           end
 > 1071 |         
 > 1072 |           default_stub  def partition(
 > 1073 |             
 > 1074 |             
 > 1075 |             & : (T ->)
 > 1076 |           ) : ::Tuple(Array(T), Array(T))
 > 1077 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1078 |           end
 > 1079 |         
 > 1080 |           default_stub  def reject(
 > 1081 |             
 > 1082 |             
 > 1083 |             & : (T ->)
 > 1084 |           )
 > 1085 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1086 |           end
 > 1087 |         
 > 1088 |           default_stub  def reject(
 > 1089 |             type : U.class, 
 > 1090 |             
 > 1091 |             
 > 1092 |           ) forall U
 > 1093 |             super
 > 1094 |           end
 > 1095 |         
 > 1096 |           default_stub  def reject(
 > 1097 |             pattern, 
 > 1098 |             
 > 1099 |             
 > 1100 |           ) : Array(T)
 > 1101 |             super
 > 1102 |           end
 > 1103 |         
 > 1104 |           default_stub  def sample(
 > 1105 |             n : Int, random = Random::DEFAULT, 
 > 1106 |             
 > 1107 |             
 > 1108 |           ) : Array(T)
 > 1109 |             super
 > 1110 |           end
 > 1111 |         
 > 1112 |           default_stub  def sample(
 > 1113 |             random = Random::DEFAULT, 
 > 1114 |             
 > 1115 |             
 > 1116 |           ) : T
 > 1117 |             super
 > 1118 |           end
 > 1119 |         
 > 1120 |           default_stub  def select(
 > 1121 |             
 > 1122 |             
 > 1123 |             & : (T ->)
 > 1124 |           )
 > 1125 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1126 |           end
 > 1127 |         
 > 1128 |           default_stub  def select(
 > 1129 |             type : U.class, 
 > 1130 |             
 > 1131 |             
 > 1132 |           ) : Array(U) forall U
 > 1133 |             super
 > 1134 |           end
 > 1135 |         
 > 1136 |           default_stub  def select(
 > 1137 |             pattern, 
 > 1138 |             
 > 1139 |             
 > 1140 |           ) : Array(T)
 > 1141 |             super
 > 1142 |           end
 > 1143 |         
 > 1144 |           default_stub  def size(
 > 1145 |             
 > 1146 |             
 > 1147 |             
 > 1148 |           ) : Int32
 > 1149 |             super
 > 1150 |           end
 > 1151 |         
 > 1152 |           default_stub  def empty?(
 > 1153 |             
 > 1154 |             
 > 1155 |             
 > 1156 |           ) : Bool
 > 1157 |             super
 > 1158 |           end
 > 1159 |         
 > 1160 |           default_stub  def skip(
 > 1161 |             count : Int, 
 > 1162 |             
 > 1163 |             
 > 1164 |           )
 > 1165 |             super
 > 1166 |           end
 > 1167 |         
 > 1168 |           default_stub  def skip_while(
 > 1169 |             
 > 1170 |             
 > 1171 |             & : (T ->)
 > 1172 |           ) : Array(T)
 > 1173 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1174 |           end
 > 1175 |         
 > 1176 |           default_stub  def sum(
 > 1177 |             initial, 
 > 1178 |             
 > 1179 |             
 > 1180 |           )
 > 1181 |             super
 > 1182 |           end
 > 1183 |         
 > 1184 |           default_stub  def sum(
 > 1185 |             
 > 1186 |             
 > 1187 |             
 > 1188 |           )
 > 1189 |             super
 > 1190 |           end
 > 1191 |         
 > 1192 |           default_stub  def sum(
 > 1193 |             initial, 
 > 1194 |             
 > 1195 |             & : (T ->)
 > 1196 |           )
 > 1197 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1198 |           end
 > 1199 |         
 > 1200 |           default_stub  def sum(
 > 1201 |             
 > 1202 |             
 > 1203 |             & : (T ->)
 > 1204 |           )
 > 1205 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1206 |           end
 > 1207 |         
 > 1208 |           default_stub private def additive_identity(
 > 1209 |             reflect, 
 > 1210 |             
 > 1211 |             
 > 1212 |           )
 > 1213 |             super
 > 1214 |           end
 > 1215 |         
 > 1216 |           default_stub  def product(
 > 1217 |             initial : Number, 
 > 1218 |             
 > 1219 |             
 > 1220 |           )
 > 1221 |             super
 > 1222 |           end
 > 1223 |         
 > 1224 |           default_stub  def product(
 > 1225 |             
 > 1226 |             
 > 1227 |             
 > 1228 |           )
 > 1229 |             super
 > 1230 |           end
 > 1231 |         
 > 1232 |           default_stub  def product(
 > 1233 |             initial : Number, 
 > 1234 |             
 > 1235 |             & : (T ->)
 > 1236 |           )
 > 1237 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1238 |           end
 > 1239 |         
 > 1240 |           default_stub  def product(
 > 1241 |             
 > 1242 |             
 > 1243 |             & : (T -> _)
 > 1244 |           )
 > 1245 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1246 |           end
 > 1247 |         
 > 1248 |           default_stub  def take_while(
 > 1249 |             
 > 1250 |             
 > 1251 |             & : (T ->)
 > 1252 |           ) : Array(T)
 > 1253 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1254 |           end
 > 1255 |         
 > 1256 |           default_stub  def tally_by(
 > 1257 |             hash, 
 > 1258 |             
 > 1259 |             &
 > 1260 |           )
 > 1261 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1262 |           end
 > 1263 |         
 > 1264 |           default_stub  def tally_by(
 > 1265 |             
 > 1266 |             
 > 1267 |             &block : (T -> U)
 > 1268 |           ) : Hash(U, Int32) forall U
 > 1269 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1270 |           end
 > 1271 |         
 > 1272 |           default_stub  def tally(
 > 1273 |             hash, 
 > 1274 |             
 > 1275 |             
 > 1276 |           )
 > 1277 |             super
 > 1278 |           end
 > 1279 |         
 > 1280 |           default_stub  def tally(
 > 1281 |             
 > 1282 |             
 > 1283 |             
 > 1284 |           ) : Hash(T, Int32)
 > 1285 |             super
 > 1286 |           end
 > 1287 |         
 > 1288 |           default_stub  def to_a(
 > 1289 |             
 > 1290 |             
 > 1291 |             
 > 1292 |           )
 > 1293 |             super
 > 1294 |           end
 > 1295 |         
 > 1296 |           default_stub  def to_h(
 > 1297 |             
 > 1298 |             
 > 1299 |             
 > 1300 |           )
 > 1301 |             super
 > 1302 |           end
 > 1303 |         
 > 1304 |           default_stub  def to_h(
 > 1305 |             
 > 1306 |             
 > 1307 |             & : (T -> Tuple(K, V))
 > 1308 |           ) forall K, V
 > 1309 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1310 |           end
 > 1311 |         
 > 1312 |           default_stub  def zip(
 > 1313 |             *others : Indexable | Iterable | Iterator, 
 > 1314 |             
 > 1315 |             &
 > 1316 |           )
 > 1317 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1318 |           end
 > 1319 |         
 > 1320 |           default_stub  def zip(
 > 1321 |             *others : Indexable | Iterable | Iterator, 
 > 1322 |             
 > 1323 |             
 > 1324 |           )
 > 1325 |             super
 > 1326 |           end
 > 1327 |         
 > 1328 |           default_stub  def zip?(
 > 1329 |             *others : Indexable | Iterable | Iterator, 
 > 1330 |             
 > 1331 |             &
 > 1332 |           )
 > 1333 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1334 |           end
 > 1335 |         
 > 1336 |           default_stub  def zip?(
 > 1337 |             *others : Indexable | Iterable | Iterator, 
 > 1338 |             
 > 1339 |             
 > 1340 |           )
 > 1341 |             super
 > 1342 |           end
 > 1343 |         
 > 1344 |           default_stub  def to_set(
 > 1345 |             
 > 1346 |             
 > 1347 |             
 > 1348 |           ) : Set(T)
 > 1349 |             super
 > 1350 |           end
 > 1351 |         
 > 1352 | 
 > 1353 |         
 > 1354 |           default_stub  def self.zip(
 > 1355 |             main, others : U, 
 > 1356 |             
 > 1357 |             &
 > 1358 |           ) forall U
 > 1359 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1360 |           end
 > 1361 |         
 > 1362 |           default_stub  def self.zip?(
 > 1363 |             main, others : U, 
 > 1364 |             
 > 1365 |             &
 > 1366 |           ) forall U
 > 1367 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1368 |           end
 > 1369 |         
 > 1370 |           default_stub  def self.element_type(
 > 1371 |             x, 
 > 1372 |             
 > 1373 |             
 > 1374 |           )
 > 1375 |             super
 > 1376 |           end
 > 1377 |         
 > 1378 |       
 > 1379 | 
 > 1380 |       
 > 1381 |         default_stub  def byte_set(
 > 1382 |           
 > 1383 |           
 > 1384 |           
 > 1385 |         ) : Set(Int32)
 > 1386 |           
 > 1387 |             super
 > 1388 |           end
 > 1389 |         
 > 1390 |       
 > 1391 |         default_stub  def char_set(
 > 1392 |           
 > 1393 |           
 > 1394 |           
 > 1395 |         ) : Set(Char)
 > 1396 |           
 > 1397 |             super
 > 1398 |           end
 > 1399 |         
 > 1400 |       
 > 1401 |         default_stub  def bytes(
 > 1402 |           
 > 1403 |           
 > 1404 |           
 > 1405 |         ) : Array(Int32)
 > 1406 |           
 > 1407 |             super
 > 1408 |           end
 > 1409 |         
 > 1410 |       
 > 1411 |         default_stub  def chars(
 > 1412 |           
 > 1413 |           
 > 1414 |           
 > 1415 |         ) : Array(Char)
 > 1416 |           
 > 1417 |             super
 > 1418 |           end
 > 1419 |         
 > 1420 |       
 > 1421 |         default_stub  def <<(
 > 1422 |           value : Char, 
 > 1423 |           
 > 1424 |           
 > 1425 |         ) : CharSet
 > 1426 |           
 > 1427 |             super
 > 1428 |           end
 > 1429 |         
 > 1430 |       
 > 1431 |         default_stub  def <<(
 > 1432 |           value : UInt8, 
 > 1433 |           
 > 1434 |           
 > 1435 |         ) : CharSet
 > 1436 |           
 > 1437 |             super
 > 1438 |           end
 > 1439 |         
 > 1440 |       
 > 1441 |         default_stub  def <<(
 > 1442 |           value : Int32, 
 > 1443 |           
 > 1444 |           
 > 1445 |         ) : CharSet
 > 1446 |           
 > 1447 |             super
 > 1448 |           end
 > 1449 |         
 > 1450 |       
 > 1451 |         default_stub  def includes_byte?(
 > 1452 |           byte : UInt8, 
 > 1453 |           
 > 1454 |           
 > 1455 |         ) : Bool
 > 1456 |           
 > 1457 |             super
 > 1458 |           end
 > 1459 |         
 > 1460 |       
 > 1461 |         default_stub  def includes_byte?(
 > 1462 |           byte : Int32, 
 > 1463 |           
 > 1464 |           
 > 1465 |         ) : Bool
 > 1466 |           
 > 1467 |             super
 > 1468 |           end
 > 1469 |         
 > 1470 |       
 > 1471 |         default_stub  def includes_char?(
 > 1472 |           char : Char, 
 > 1473 |           
 > 1474 |           
 > 1475 |         ) : Bool
 > 1476 |           
 > 1477 |             super
 > 1478 |           end
 > 1479 |         
 > 1480 |       
 > 1481 |         default_stub  def includes?(
 > 1482 |           byte : UInt8 | Int32, 
 > 1483 |           
 > 1484 |           
 > 1485 |         ) : Bool
 > 1486 |           
 > 1487 |             super
 > 1488 |           end
 > 1489 |         
 > 1490 |       
 > 1491 |         default_stub  def includes?(
 > 1492 |           char : Char, 
 > 1493 |           
 > 1494 |           
 > 1495 |         ) : Bool
 > 1496 |           
 > 1497 |             super
 > 1498 |           end
 > 1499 |         
 > 1500 |       
 > 1501 |         default_stub  def each_byte(
 > 1502 |           
 > 1503 |           
 > 1504 |           &block : (Int32 ->)
 > 1505 |         )
 > 1506 |           
 > 1507 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1508 |           end
 > 1509 |         
 > 1510 |       
 > 1511 |         default_stub  def each_char(
 > 1512 |           
 > 1513 |           
 > 1514 |           &block : (Char ->)
 > 1515 |         )
 > 1516 |           
 > 1517 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1518 |           end
 > 1519 |         
 > 1520 |       
 > 1521 |         default_stub  def each(
 > 1522 |           *args, 
 > 1523 |           **options, 
 > 1524 |           
 > 1525 |         )
 > 1526 |           
 > 1527 |             super
 > 1528 |           end
 > 1529 |         
 > 1530 |       
 > 1531 |         default_stub  def each(
 > 1532 |           *args, 
 > 1533 |           **options, 
 > 1534 |           &
 > 1535 |         )
 > 1536 |           
 > 1537 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1538 |           end
 > 1539 |         
 > 1540 |       
 > 1541 |         default_stub  def select_bytes(
 > 1542 |           
 > 1543 |           
 > 1544 |           &block : (Int32 -> Bool)
 > 1545 |         ) : Array(Int32)
 > 1546 |           
 > 1547 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1548 |           end
 > 1549 |         
 > 1550 |       
 > 1551 |         default_stub  def select_chars(
 > 1552 |           
 > 1553 |           
 > 1554 |           &block : (Char -> Bool)
 > 1555 |         ) : Array(Char)
 > 1556 |           
 > 1557 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1558 |           end
 > 1559 |         
 > 1560 |       
 > 1561 |         default_stub  def select(
 > 1562 |           *args, 
 > 1563 |           **options, 
 > 1564 |           
 > 1565 |         )
 > 1566 |           
 > 1567 |             super
 > 1568 |           end
 > 1569 |         
 > 1570 |       
 > 1571 |         default_stub  def select(
 > 1572 |           *args, 
 > 1573 |           **options, 
 > 1574 |           &
 > 1575 |         )
 > 1576 |           
 > 1577 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1578 |           end
 > 1579 |         
 > 1580 |       
 > 1581 |         default_stub  def map_bytes(
 > 1582 |           
 > 1583 |           
 > 1584 |           &block : (Int32 -> T)
 > 1585 |         ) : Array(T) forall T
 > 1586 |           
 > 1587 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1588 |           end
 > 1589 |         
 > 1590 |       
 > 1591 |         default_stub  def map_chars(
 > 1592 |           
 > 1593 |           
 > 1594 |           &block : (Char -> T)
 > 1595 |         ) : Array(T) forall T
 > 1596 |           
 > 1597 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1598 |           end
 > 1599 |         
 > 1600 |       
 > 1601 |         default_stub  def map(
 > 1602 |           *args, 
 > 1603 |           **options, 
 > 1604 |           
 > 1605 |         )
 > 1606 |           
 > 1607 |             super
 > 1608 |           end
 > 1609 |         
 > 1610 |       
 > 1611 |         default_stub  def map(
 > 1612 |           *args, 
 > 1613 |           **options, 
 > 1614 |           &
 > 1615 |         )
 > 1616 |           
 > 1617 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1618 |           end
 > 1619 |         
 > 1620 |       
 > 1621 |         default_stub  def random_byte(
 > 1622 |           random = Random::DEFAULT, 
 > 1623 |           
 > 1624 |           
 > 1625 |         ) : Int32
 > 1626 |           
 > 1627 |             super
 > 1628 |           end
 > 1629 |         
 > 1630 |       
 > 1631 |         default_stub  def random_char(
 > 1632 |           random = Random::DEFAULT, 
 > 1633 |           
 > 1634 |           
 > 1635 |         ) : Char
 > 1636 |           
 > 1637 |             super
 > 1638 |           end
 > 1639 |         
 > 1640 |       
 > 1641 |         default_stub  def each_random_byte(
 > 1642 |           n : Int, 
 > 1643 |           
 > 1644 |           &block : (Int32 ->)
 > 1645 |         )
 > 1646 |           
 > 1647 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1648 |           end
 > 1649 |         
 > 1650 |       
 > 1651 |         default_stub  def each_random_char(
 > 1652 |           n : Int, 
 > 1653 |           
 > 1654 |           &block : (Char ->)
 > 1655 |         )
 > 1656 |           
 > 1657 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1658 |           end
 > 1659 |         
 > 1660 |       
 > 1661 |         default_stub  def random_bytes(
 > 1662 |           length : Int, random = Random::DEFAULT, 
 > 1663 |           
 > 1664 |           
 > 1665 |         ) : Array(Int32)
 > 1666 |           
 > 1667 |             super
 > 1668 |           end
 > 1669 |         
 > 1670 |       
 > 1671 |         default_stub  def random_bytes(
 > 1672 |           lengths : Array(Int) | Range(Int, Int), random = Random::DEFAULT, 
 > 1673 |           
 > 1674 |           
 > 1675 |         ) : Array(Int32)
 > 1676 |           
 > 1677 |             super
 > 1678 |           end
 > 1679 |         
 > 1680 |       
 > 1681 |         default_stub  def random_chars(
 > 1682 |           length : Int, random = Random::DEFAULT, 
 > 1683 |           
 > 1684 |           
 > 1685 |         ) : Array(Char)
 > 1686 |           
 > 1687 |             super
 > 1688 |           end
 > 1689 |         
 > 1690 |       
 > 1691 |         default_stub  def random_chars(
 > 1692 |           lengths : Array(Int) | Range(Int, Int), random = Random::DEFAULT, 
 > 1693 |           
 > 1694 |           
 > 1695 |         ) : Array(Char)
 > 1696 |           
 > 1697 |             super
 > 1698 |           end
 > 1699 |         
 > 1700 |       
 > 1701 |         default_stub  def random_string(
 > 1702 |           length : Int | Array(Int) | Range(Int, Int), 
 > 1703 |           
 > 1704 |           
 > 1705 |         ) : String
 > 1706 |           
 > 1707 |             super
 > 1708 |           end
 > 1709 |         
 > 1710 |       
 > 1711 |         default_stub  def random_distinct_bytes(
 > 1712 |           length : Int, 
 > 1713 |           
 > 1714 |           
 > 1715 |         ) : Array(Int32)
 > 1716 |           
 > 1717 |             super
 > 1718 |           end
 > 1719 |         
 > 1720 |       
 > 1721 |         default_stub  def random_distinct_bytes(
 > 1722 |           length : Array(Int), random = Random::DEFAULT, 
 > 1723 |           
 > 1724 |           
 > 1725 |         ) : Array(Int32)
 > 1726 |           
 > 1727 |             super
 > 1728 |           end
 > 1729 |         
 > 1730 |       
 > 1731 |         default_stub  def random_distinct_bytes(
 > 1732 |           length : Range(Int, Int), 
 > 1733 |           
 > 1734 |           
 > 1735 |         ) : Array(Int32)
 > 1736 |           
 > 1737 |             super
 > 1738 |           end
 > 1739 |         
 > 1740 |       
 > 1741 |         default_stub  def random_distinct_chars(
 > 1742 |           length : Int, 
 > 1743 |           
 > 1744 |           
 > 1745 |         ) : Array(Char)
 > 1746 |           
 > 1747 |             super
 > 1748 |           end
 > 1749 |         
 > 1750 |       
 > 1751 |         default_stub  def random_distinct_chars(
 > 1752 |           length : Array(Int), random = Random::DEFAULT, 
 > 1753 |           
 > 1754 |           
 > 1755 |         ) : Array(Char)
 > 1756 |           
 > 1757 |             super
 > 1758 |           end
 > 1759 |         
 > 1760 |       
 > 1761 |         default_stub  def random_distinct_chars(
 > 1762 |           length : Range(Int, Int), 
 > 1763 |           
 > 1764 |           
 > 1765 |         ) : Array(Char)
 > 1766 |           
 > 1767 |             super
 > 1768 |           end
 > 1769 |         
 > 1770 |       
 > 1771 |         default_stub  def random_distinct_string(
 > 1772 |           length : Int | Array(Int) | Range(Int, Int), 
 > 1773 |           
 > 1774 |           
 > 1775 |         ) : String
 > 1776 |           
 > 1777 |             super
 > 1778 |           end
 > 1779 |         
 > 1780 |       
 > 1781 |         default_stub  def each_substring_with_index(
 > 1782 |           data : String, min_length : Int = 4, 
 > 1783 |           
 > 1784 |           &block : (String, Int32 ->)
 > 1785 |         )
 > 1786 |           
 > 1787 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1788 |           end
 > 1789 |         
 > 1790 |       
 > 1791 |         default_stub  def substrings_with_indexes(
 > 1792 |           data : String, min_length : Int = 4, 
 > 1793 |           
 > 1794 |           
 > 1795 |         ) : Array(Tuple(String, Int32))
 > 1796 |           
 > 1797 |             super
 > 1798 |           end
 > 1799 |         
 > 1800 |       
 > 1801 |         default_stub  def each_substring(
 > 1802 |           data : String, min_length : Int = 4, 
 > 1803 |           
 > 1804 |           &block : (String ->)
 > 1805 |         )
 > 1806 |           
 > 1807 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1808 |           end
 > 1809 |         
 > 1810 |       
 > 1811 |         default_stub  def substrings(
 > 1812 |           data : String, min_length : Int = 4, 
 > 1813 |           
 > 1814 |           
 > 1815 |         ) : Array(String)
 > 1816 |           
 > 1817 |             super
 > 1818 |           end
 > 1819 |         
 > 1820 |       
 > 1821 |         default_stub  def |(
 > 1822 |           other : CharSet, 
 > 1823 |           
 > 1824 |           
 > 1825 |         ) : CharSet
 > 1826 |           
 > 1827 |             super
 > 1828 |           end
 > 1829 |         
 > 1830 |       
 > 1831 |         default_stub  def +(
 > 1832 |           other : CharSet, 
 > 1833 |           
 > 1834 |           
 > 1835 |         ) : CharSet
 > 1836 |           
 > 1837 |             super
 > 1838 |           end
 > 1839 |         
 > 1840 |       
 > 1841 |         default_stub  def -(
 > 1842 |           other : CharSet, 
 > 1843 |           
 > 1844 |           
 > 1845 |         ) : CharSet
 > 1846 |           
 > 1847 |             super
 > 1848 |           end
 > 1849 |         
 > 1850 |       
 > 1851 |         default_stub  def &(
 > 1852 |           other : CharSet, 
 > 1853 |           
 > 1854 |           
 > 1855 |         ) : CharSet
 > 1856 |           
 > 1857 |             super
 > 1858 |           end
 > 1859 |         
 > 1860 |       
 > 1861 |         default_stub  def intersects?(
 > 1862 |           other : CharSet, 
 > 1863 |           
 > 1864 |           
 > 1865 |         ) : Bool
 > 1866 |           
 > 1867 |             super
 > 1868 |           end
 > 1869 |         
 > 1870 |       
 > 1871 |         default_stub  def subset_of?(
 > 1872 |           other : CharSet, 
 > 1873 |           
 > 1874 |           
 > 1875 |         ) : Bool
 > 1876 |           
 > 1877 |             super
 > 1878 |           end
 > 1879 |         
 > 1880 |       
 > 1881 |         default_stub  def ==(
 > 1882 |           other : CharSet, 
 > 1883 |           
 > 1884 |           
 > 1885 |         ) : Bool
 > 1886 |           
 > 1887 |             super
 > 1888 |           end
 > 1889 |         
 > 1890 |       
 > 1891 |         default_stub  def ===(
 > 1892 |           other : String, 
 > 1893 |           
 > 1894 |           
 > 1895 |         ) : Bool
 > 1896 |           
 > 1897 |             super
 > 1898 |           end
 > 1899 |         
 > 1900 |       
 > 1901 |         default_stub  def =~(
 > 1902 |           string : String, 
 > 1903 |           
 > 1904 |           
 > 1905 |         )
 > 1906 |           
 > 1907 |             super
 > 1908 |           end
 > 1909 |         
 > 1910 |       
 > 1911 |         default_stub  def to_a(
 > 1912 |           *args, 
 > 1913 |           **options, 
 > 1914 |           
 > 1915 |         )
 > 1916 |           
 > 1917 |             super
 > 1918 |           end
 > 1919 |         
 > 1920 |       
 > 1921 |         default_stub  def to_a(
 > 1922 |           *args, 
 > 1923 |           **options, 
 > 1924 |           &
 > 1925 |         )
 > 1926 |           
 > 1927 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1928 |           end
 > 1929 |         
 > 1930 |       
 > 1931 |         default_stub  def to_set(
 > 1932 |           *args, 
 > 1933 |           **options, 
 > 1934 |           
 > 1935 |         )
 > 1936 |           
 > 1937 |             super
 > 1938 |           end
 > 1939 |         
 > 1940 |       
 > 1941 |         default_stub  def to_set(
 > 1942 |           *args, 
 > 1943 |           **options, 
 > 1944 |           &
 > 1945 |         )
 > 1946 |           
 > 1947 |             super { |*__temp_1063| yield *__temp_1063 }
 > 1948 |           end
 > 1949 |         
 > 1950 |       
 > 1951 | 
 > 1952 |       
 > 1953 |         default_stub  def self.new(
 > 1954 |           values : Enumerable(UInt8 | Int32 | Char), 
 > 1955 |           
 > 1956 |           
 > 1957 |         )
 > 1958 |           super
 > 1959 |         end
 > 1960 |       
 > 1961 |         default_stub  def self.new(
 > 1962 |           values : Indexable(UInt8 | Int32 | Char), 
 > 1963 |           
 > 1964 |           
 > 1965 |         )
 > 1966 |           super
 > 1967 |         end
 > 1968 |       
 > 1969 |         default_stub  def self.new(
 > 1970 |           
 > 1971 |           
 > 1972 |           
 > 1973 |         )
 > 1974 |           super
 > 1975 |         end
 > 1976 |       
 > 1977 |         default_stub  def self.[](
 > 1978 |           *values : UInt8 | Int32 | Char | Range(UInt8, UInt8) | Range(Int32, Int32) | Range(Char, Char), 
 > 1979 |           
 > 1980 |           
 > 1981 |         ) : CharSet
 > 1982 |           super
 > 1983 |         end
 > 1984 |       
 > 1985 |     
Error: expanding macro

In lib/spectator/src/spectator/mocks/stubbable.cr:161:58

 161 | {{ if method.return_type && method.return_type.resolve == NoReturn
                                                      ^------
Error: undefined constant U

In /var/lib/snapd/snap/crystal/1384/share/crystal/src/enumerable.cr:466:48

 466 | def each_with_object(obj : U, & : T, U ->) : U forall U
                                                    ^
Error: undefined constant U
icy-arctic-fox commented 1 year ago

It appears that the mock code doesn't account for free variables in return types.

icy-arctic-fox commented 1 year ago

A fix for this issue and various related ones has been pushed to master. Can you confirm this fixes the issue with free variables in type annotations? I suspect there may be other issues porting chars.cr to the latest Spectator mocks. Please open an issue if you encounter any.

postmodern commented 1 year ago

@icy-arctic-fox awesome, that got me further. I now think I'm hitting another spectator bug.

Example code:

    #
    # Returns an Array of random, but unique, bytes from the `CharSet`.
    #
    def random_distinct_bytes(length : Int) : Array(Int32)
      @byte_set.to_a.shuffle[0,length]
    end

    #
    # Returns an Array of random, but unique, bytes from the `CharSet`.
    #
    def random_distinct_bytes(length : Array(Int),
                              random = Random::DEFAULT) : Array(Int32)
      bytes.shuffle[0,length.sample(random)]
    end

    #
    # Returns an Array of random, but unique, bytes from the `CharSet`.
    #
    def random_distinct_bytes(length : Range(Int, Int)) : Array(Int32)
      @byte_set.to_a.shuffle[0,rand(length)]
    end

Example spec code:

  describe "#random_distinct_bytes" do
    it "must return a random Array of unique bytes" do
      bytes = subject.random_distinct_bytes(10)

      expect(bytes.uniq).to be == bytes
      expect(bytes.all? { |b| subject.includes?(b) }).to be(true)
    end

    context "with a range of lengths" do
      it "must return a random Array of unique bytes with a varying length" do
        bytes = subject.random_distinct_bytes(5..10)

        expect(bytes.uniq).to be == bytes
        expect(bytes.size).to be_between(5, 10)
        expect(bytes.all? { |b| subject.includes?(b) }).to be(true)
      end
    end
  end

Error:

...

There was a problem expanding macro 'default_stub'

Called macro defined in lib/spectator/src/spectator/mocks/stubbable.cr:108:13

 108 | private macro default_stub(method)

Which expanded to:

    1 |       
    2 |       
    3 |       
    4 |       
    5 | 
    6 |        def random_distinct_bytes(
    7 |         length : Range(Int, Int), 
    8 |         
    9 |         
   10 |       ) : Array(Int32)
   11 |         super(length)
   12 |       end
   13 | 
   14 |       
   15 | 
   16 |       
   17 |        def random_distinct_bytes(
   18 |         length : Range(Int, Int), 
   19 |         
   20 |         
   21 |       ) : Array(Int32)
   22 | 
   23 |         # Capture information about the call.
 > 24 |         __temp_1575 = ::Spectator::MethodCall.build(
   25 |           :random_distinct_bytes,
   26 |           ::NamedTuple.new(
   27 |             "length": length, 
   28 |           ),
   29 |           
   30 |           ::NamedTuple.new(
   31 |             
   32 |           ).merge()
   33 |         )
   34 |         _spectator_record_call(__temp_1575)
   35 | 
   36 |         # Attempt to find a stub that satisfies the method call and arguments.
   37 |         # Finding a suitable stub is delegated to the type including the `Stubbable` module.
   38 |         if __temp_1576 = _spectator_find_stub(__temp_1575)
   39 |           # Cast the stub or return value to the expected type.
   40 |           # This is necessary to match the expected return type of the original method.
   41 |           _spectator_cast_stub_value(__temp_1576, __temp_1575, typeof(previous_def),
   42 |           :raise)
   43 |         else
   44 |           # Delegate missing stub behavior to concrete type.
   45 |           _spectator_stub_fallback(__temp_1575, typeof(previous_def)) do
   46 |             # Use the default response for the method.
   47 |             previous_def
   48 |           end
   49 |         end
   50 |       end
   51 |     
Error: instantiating 'Spectator::MethodCall.class#build(Symbol, NamedTuple(length: Range(Int32, Int32)), NamedTuple())'

In lib/spectator/src/spectator/mocks/method_call.cr:27:35

 27 | arguments = FormalArguments.build(*args, **kwargs).as(AbstractArguments)
                                  ^----
Error: instantiating 'Spectator::FormalArguments(Args, Splat, DoubleSplat).class#build(Tuple(NamedTuple(length: Range(Int32, Int32)), NamedTuple()), NamedTuple())'

In lib/spectator/src/spectator/mocks/formal_arguments.cr:36:7

 36 | new(args, nil, nil, kwargs)
      ^--
Error: instantiating 'new(NamedTuple(length: Range(Int32, Int32)), Nil, Nil, NamedTuple())'

Error: instantiating 'Spectator::AbstractArguments+#===(Spectator::AbstractArguments+)'

In lib/spectator/src/spectator/mocks/stub.cr:47:18

 47 | constraint === call.arguments
                 ^-
Error: instantiating 'Spectator::AbstractArguments+#===(Spectator::AbstractArguments+)'

In lib/spectator/src/spectator/mocks/formal_arguments.cr:130:7

 130 | compare_named_tuples(args, other.args) && compare_tuples(splat, other.splat) && compare_named_tuples(kwargs, other.kwargs)
       ^-------------------
Error: instantiating 'compare_named_tuples(NamedTuple(length: Range(Int32, Int32)), (NamedTuple() | NamedTuple(byte: Int32 | UInt8) | NamedTuple(char: Char) | NamedTuple(io: String::Builder) | NamedTuple(length: Int32 | Range(Int32, Int32)) | NamedTuple(length: Int32, random: Random::PCG32) | NamedTuple(method: Symbol) | NamedTuple(n: Int32) | NamedTuple(random: Random::PCG32) | NamedTuple(value: Char)))'

In lib/spectator/src/spectator/mocks/abstract_arguments.cr:35:9

 35 | a.each do |k, v1|
        ^---
Error: instantiating 'NamedTuple(length: Range(Int32, Int32))#each()'

In lib/spectator/src/spectator/mocks/abstract_arguments.cr:35:9

 35 | a.each do |k, v1|
        ^---
Error: instantiating 'NamedTuple(length: Range(Int32, Int32))#each()'

In lib/spectator/src/spectator/mocks/abstract_arguments.cr:42:34

 42 | return false unless v1 === v2
                             ^-
Error: instantiating 'Range(Int32, Int32)#===((Char | Int32 | Random::PCG32 | Range(Int32, Int32) | String::Builder | Symbol | UInt8))'

In /var/lib/snapd/snap/crystal/1384/share/crystal/src/range.cr:327:5

 327 | includes?(value)
       ^--------
Error: instantiating 'includes?((Char | Int32 | Random::PCG32 | Range(Int32, Int32) | String::Builder | Symbol | UInt8))'

In /var/lib/snapd/snap/crystal/1384/share/crystal/src/range.cr:298:35

 298 | (begin_value.nil? || value >= begin_value) &&
                                     ^----------
Error: expected argument #1 to 'Char#>=' to be Char, not Int32

Overloads are:
 - Char#>=(other : Char)
 - Comparable(T)#>=(other : T)

errors.log

icy-arctic-fox commented 1 year ago

Pushed another change to master that should fix range comparisons.

The underlying issue is that a union of argument types are being compared against each other. Case-equality matching (===) is used. This creates all sorts of combinations like (in your case):

(1..10) === 'a'

Which doesn't make sense, but could be a possible comparison with the union types. What I'm doing for now is using == for when === doesn't make sense. This is case-by-case. The problem with this is that any custom types defining a === method with no type restrictions may also hit this. I'm at least trying to cover the standard library types.

If you (or anyone else) has a better solution, I'd love to hear it!

postmodern commented 1 year ago

@icy-arctic-fox got a little further.

Crystal code:

    @[AlwaysInline]
    def +(other : CharSet) : CharSet
      self | other
    end

Crystal spec:

  describe "#+" do
    mock Chars::CharSet do
      stub :|, other : Chars::CharSet
    end

    let(other) { described_class.new }
    let(return_value) { described_class.new }

    it "must call #+" do
      expect(subject).to receive(:|).with(other).and_return(return_value)

      expect(subject + other).to be(return_value)
    end
  end

Error:

In spec/char_set_spec.cr:658:1

 658 | it "must call #+" do
      ^
Error: expanding macro

There was a problem expanding macro 'it'

Called macro defined in macro 'define_example'

 17 | macro it(what = nil, *tags, **metadata, &block)

Which expanded to:

 >  1 |         
 >  2 |         
 >  3 | 
 >  4 |         _spectator_metadata(__temp_46, :metadata,  )
 >  5 |         _spectator_metadata(__temp_731, __temp_46,  )
 >  6 | 
 >  7 |         
 >  8 |           
 >  9 | 
 > 10 |           private def __temp_732() : Nil
 > 11 |             (expect(subject)).to(((receive(:|)).with(other)).and_return(return_value))
 > 12 | (expect(subject + other)).to(be(return_value))
 > 13 | 
 > 14 |           end
 > 15 | 
 > 16 |           ::Spectator::DSL::Builder.add_example(
 > 17 |             _spectator_example_name("must call #+"),
 > 18 |             ::Spectator::Location.new("/home/postmodern/code/crystal/chars.cr/spec/char_set_spec.cr", 658, 662),
 > 19 |             -> { new.as(::Spectator::Context) },
 > 20 |             __temp_731
 > 21 |           ) do |example|
 > 22 |             example.with_context(SpectatorTestContext::Group__temp_205::Group__temp_726) do
 > 23 |               
 > 24 |                 __temp_732
 > 25 |               
 > 26 |             end
 > 27 |           end
 > 28 | 
 > 29 |         
 > 30 |       
Error: instantiating 'Spectator::Example#with_context(SpectatorTestContext::Group__temp_205::Group__temp_726.class)'

In spec/char_set_spec.cr:658:1

 658 | it "must call #+" do
      ^
Error: expanding macro

There was a problem expanding macro 'it'

Called macro defined in macro 'define_example'

 17 | macro it(what = nil, *tags, **metadata, &block)

Which expanded to:

 >  1 |         
 >  2 |         
 >  3 | 
 >  4 |         _spectator_metadata(__temp_46, :metadata,  )
 >  5 |         _spectator_metadata(__temp_731, __temp_46,  )
 >  6 | 
 >  7 |         
 >  8 |           
 >  9 | 
 > 10 |           private def __temp_732() : Nil
 > 11 |             (expect(subject)).to(((receive(:|)).with(other)).and_return(return_value))
 > 12 | (expect(subject + other)).to(be(return_value))
 > 13 | 
 > 14 |           end
 > 15 | 
 > 16 |           ::Spectator::DSL::Builder.add_example(
 > 17 |             _spectator_example_name("must call #+"),
 > 18 |             ::Spectator::Location.new("/home/postmodern/code/crystal/chars.cr/spec/char_set_spec.cr", 658, 662),
 > 19 |             -> { new.as(::Spectator::Context) },
 > 20 |             __temp_731
 > 21 |           ) do |example|
 > 22 |             example.with_context(SpectatorTestContext::Group__temp_205::Group__temp_726) do
 > 23 |               
 > 24 |                 __temp_732
 > 25 |               
 > 26 |             end
 > 27 |           end
 > 28 | 
 > 29 |         
 > 30 |       
Error: instantiating '__temp_732()'

In spec/char_set_spec.cr:659:24

 659 | expect(subject).to receive(:|).with(other).and_return(return_value)
                        ^-
Error: instantiating 'Spectator::Expectation::Target(Chars::CharSet)#to(Spectator::ValueStub(Chars::CharSet))'

In lib/spectator/src/spectator/expectation.cr:104:7

 104 | def to(stub : Stub, message = nil) : Nil
       ^-
Error: The syntax `expect(...).to receive(...)` requires the expression passed to `expect` be stubbable (a mock or double)
icy-arctic-fox commented 1 year ago

It looks like the old (v0.9) stub syntax is being used. A method definition (def) is required after the stub keyword. That should have raised a compiler error, so I'll look into that...

    mock Chars::CharSet do
      stub :|, other : Chars::CharSet
    end

# can be just:

mock Chars::CharSet

The v0.11 syntax doesn't require a stub entry for each stubbed method. The mocked type also has to be instantiated with mock(Type).

I think this code should work:

Spectator.describe Chars::CharSet do
  mock Chars::CharSet

  describe "#|" do
    let(other) { mock(Chars::CharSet) }
    let(return_value) { mock(Chars::CharSet) }

    it "must call #+" do
      expect(subject).to receive(:|).with(other).and_return(return_value)

      expect(subject | other).to be(return_value)
    end
  end
end

More info about the new syntax and mock system can be found on the wiki.

postmodern commented 1 year ago

Success! After adding the double mock statements it worked. I'm curious why are two mock statements required, in the specs and another within a let/subject?

icy-arctic-fox commented 1 year ago

I was attempting to copy the code you had before. This bit from the original:

    let(other) { described_class.new }
    let(return_value) { described_class.new }

The mock outside of the it block is a macro that defines a sub-type which mocks the original. The mock inside of a test block (or any other function like let) instantiates the previously defined mock. These can be replaced with def_mock and new_mock respectively if it makes more sense.

Spectator.describe Chars::CharSet do
  def_mock Chars::CharSet

  let(other) { new_mock(Chars::CharSet) }
  let(return_value) { new_mock(Chars::CharSet) }
end

Hope that makes sense. :confused:

I'm glad it works now! Real world usages of Spectator are invaluable for testing it.