class T::InterfaceWrapper

def initialize(target_obj, interface_mod)

def initialize(target_obj, interface_mod)
  if target_obj.is_a?(T::InterfaceWrapper)
    # wrapped_dynamic_cast should guarantee this never happens.
    raise "Unexpected: wrapping a wrapper. Please report to #dev-productivity."
  end
  if !target_obj.is_a?(interface_mod)
    # wrapped_dynamic_cast should guarantee this never happens.
    raise "Unexpected: `is_a?` failed. Please report to #dev-productivity."
  end
  if target_obj.class == interface_mod
    # wrapped_dynamic_cast should guarantee this never happens.
    raise "Unexpected: exact class match. Please report to #dev-productivity."
  end
  @target_obj = target_obj
  @interface_mod = interface_mod
  self_methods = self.class.self_methods
  # If perf becomes an issue, we can define these on an anonymous subclass, and keep a cache
  # so we only need to do it once per unique `interface_mod`
  T::Utils.methods_excluding_object(interface_mod).each do |method_name|
    if self_methods.include?(method_name)
      raise "interface_mod has a method that conflicts with #{self.class}: #{method_name}"
    end
    define_singleton_method(method_name) do |*args, &blk|
      target_obj.send(method_name, *args, &blk)
    end
    if target_obj.singleton_class.public_method_defined?(method_name)
      # no-op, it's already public
    elsif target_obj.singleton_class.protected_method_defined?(method_name)
      singleton_class.send(:protected, method_name)
    elsif target_obj.singleton_class.private_method_defined?(method_name)
      singleton_class.send(:private, method_name)
    else
      raise "This should never happen. Report to #dev-productivity"
    end
  end
end