module T::Private::Methods
def self._check_final_ancestors(target, target_ancestors, source_method_names)
the final instance methods of target and source_method_names. so, for every m in source_method_names, check if there
when target includes a module with instance methods source_method_names, ensure there is zero intersection between
def self._check_final_ancestors(target, target_ancestors, source_method_names) if !module_with_final?(target) return end # use reverse_each to check farther-up ancestors first, for better error messages. we could avoid this if we were on # the version of ruby that adds the optional argument to method_defined? that allows you to exclude ancestors. target_ancestors.reverse_each do |ancestor| source_method_names.each do |method_name| # the usage of method_owner_and_name_to_key(ancestor, method_name) instead of # method_to_key(ancestor.instance_method(method_name)) is not (just) an optimization, but also required for # correctness, since ancestor.method_defined?(method_name) may return true even if method_name is not defined # directly on ancestor but instead an ancestor of ancestor. if ancestor.method_defined?(method_name) && final_method?(method_owner_and_name_to_key(ancestor, method_name)) raise( "`#{ancestor.name}##{method_name}` was declared as final and cannot be " + (target == ancestor ? "redefined" : "overridden in `#{target.name}`") ) end end end end