def match(other)
      other = other.type if other.instance_of? AnnotatedArgType
      return true if other.instance_of? WildQuery
      return false unless other.instance_of? MethodType
      return false unless @ret.match(other.ret)
      if @block == nil
        return false unless other.block == nil
      else
        return false if other.block == nil
        return false unless @block.match(other.block)
      end
      # Check arg matches; logic is similar to pre_cond
      states = [[0,0]] # [position in self, position in other]
      until states.empty?
        s_arg, o_arg = states.pop
        return true if s_arg == @args.size && o_arg == other.args.size # everything matches
        next if s_arg >= @args.size # match not possible, not enough args in self
        if @args[s_arg].instance_of? DotsQuery then
          if o_arg == other.args.size
            # no args left in other, skip ...
            states << [s_arg+1, o_arg]
          else
            states << [s_arg+1, o_arg+1] # match, no more matches to ...
            states << [s_arg, o_arg+1]   # match, more matches to ... coming
          end
        else
          next if o_arg == other.args.size # match not possible, not enough args in other
          s_arg_t = @args[s_arg]
          s_arg_t = s_arg_t.type if s_arg_t.instance_of? AnnotatedArgType
          o_arg_t = other.args[o_arg]
          o_arg_t = o_arg_t.type if o_arg_t.instance_of? AnnotatedArgType
          next unless s_arg_t.match(o_arg_t)
          states << [s_arg+1, o_arg+1]
        end
      end
      return false
    end
def match(other)
      other = other.type if other.instance_of? AnnotatedArgType
      return true if other.instance_of? WildQuery
      return false unless other.instance_of? MethodType
      return false unless @ret.match(other.ret)
      if @block == nil
        return false unless other.block == nil
      else
        return false if other.block == nil
        return false unless @block.match(other.block)
      end
      # Check arg matches; logic is similar to pre_cond
      states = [[0,0]] # [position in self, position in other]
      until states.empty?
        s_arg, o_arg = states.pop
        return true if s_arg == @args.size && o_arg == other.args.size # everything matches
        next if s_arg >= @args.size # match not possible, not enough args in self
        if @args[s_arg].instance_of? DotsQuery then
          if o_arg == other.args.size
            # no args left in other, skip ...
            states << [s_arg+1, o_arg]
          else
            states << [s_arg+1, o_arg+1] # match, no more matches to ...
            states << [s_arg, o_arg+1]   # match, more matches to ... coming
          end
        else
          next if o_arg == other.args.size # match not possible, not enough args in other
          s_arg_t = @args[s_arg]
          s_arg_t = s_arg_t.type if s_arg_t.instance_of? AnnotatedArgType
          o_arg_t = other.args[o_arg]
          o_arg_t = o_arg_t.type if o_arg_t.instance_of? AnnotatedArgType
          next unless s_arg_t.match(o_arg_t)
          states << [s_arg+1, o_arg+1]
        end
      end
      return false
    end
other may not be a query