-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Strange error where exception backtrace shows that it came from SiB #132
Comments
Note that this refactoring did not have the issue: class Sig
INSTANCE = new
def declared(mod, param_types)
@current = [mod, param_types]
self
end
def returns(return_type)
@current << return_type if @current
self
end
def observed(method)
return unless @current
mod, param_types, return_type = @current
@current = nil
known[mod][method.name] = {receives: param_types, returns: return_type}
declared = param_types.keys.sort
observed = method.parameters.map(&:last).sort
declared == observed or raise TypeError, <<~MSG
Sig doesn't match the method for #{mod}##{method.name}
declared: #{declared.inspect}
observed: #{observed.inspect}
MSG
end
def check_call(binding, obj, method_name)
return unless sig = get_sig(obj, method_name)
sig[:receives].each do |name, type|
value = binding.local_variable_get name
next if value.kind_of? type
raise TypeError, "#{name} was #{value.inspect}, but expected a #{type.inspect}"
end
end
def check_return(obj, method_name, value)
return unless sig = get_sig(obj, method_name)
return if value.kind_of? sig[:returns]
raise TypeError, "#{method_name} returned #{value.inspect}, but expected a #{sig[:returns].inspect}"
end
private
def known
@known ||= Hash.new { |h, mod| h[mod] = {} }
end
def get_sig(obj, method_name)
known.key?(obj.class) && known[obj.class][method_name]
end
end
class Module
def sig(**types)
Sig::INSTANCE.declared(self, types)
end
def method_added(name)
Sig::INSTANCE.observed instance_method(name)
rescue TypeError
$!.set_backtrace caller.drop(1)
raise
end
end
erroring = false # need this b/c, tp will still call return (w/ return_value set to nil)
TracePoint.trace :call, :return do |tp|
if erroring
erroring = false
next
end
begin
case tp.event
when :call
Sig::INSTANCE.check_call tp.binding, tp.self, tp.method_id
when :return
Sig::INSTANCE.check_return tp.self, tp.method_id, tp.return_value
end
rescue TypeError
$!.set_backtrace caller.drop(1)
erroring = true
raise
end
end
###############################################
class BoxedInt
sig(val: Integer).returns(Integer)
def initialize(val)
@val = val
end
sig(num: Integer).returns(BoxedInt)
def + num2 # ~> TypeError: Sig doesn't match the method for BoxedInt#+\n declared: [:num]\n observed: [:num2]\n
BoxedInt.new @val + num
end
sig(num: Integer).returns(BoxedInt)
def - num
BoxedInt.new @val - num
end
sig.returns(String)
def inspect
"BoxedInt.new(#{@val.inspect})"
end
end
n = BoxedInt.new 2
n + 10 # =>
n - 3 # =>
n + 5 - 3 # =>
# ~> TypeError
# ~> Sig doesn't match the method for BoxedInt#+
# ~> declared: [:num]
# ~> observed: [:num2]
# ~>
# ~> /var/folders/7g/mbft22555w3_2nqs_h1kbglw0000gn/T/seeing_is_believing_temp_dir20180607-91903-1lu6wgo/program.rb:97:in `<class:BoxedInt>'
# ~> /var/folders/7g/mbft22555w3_2nqs_h1kbglw0000gn/T/seeing_is_believing_temp_dir20180607-91903-1lu6wgo/program.rb:90:in `<main>' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
While playing with it, I changed the arg to
BoxedInt#-
to be namednum2
, the backtrace says it comes from sib/the_matrix.rbI don't really understand what's going on here, maybe a bug.
The text was updated successfully, but these errors were encountered: