Skip to content

Allow "overwriting" a final method if it's an abstract method - #10652

Draft
aisamanra wants to merge 4 commits into
masterfrom
gdritter/allow-including-abstract-over-final
Draft

aisamanra wants to merge 4 commits into
masterfrom
gdritter/allow-including-abstract-over-final

Conversation

@aisamanra

Copy link
Copy Markdown
Contributor

This change addresses an order-dependence that happens between sig(:final) methods and mixins by making the final machinery skip cases where the "override" is actually an abstract method which would defer to the final method.

Motivation

Previously, if we had a final method already defined (e.g. from a parent class) and we included a mixin which defines that method, we'd raise an error. However, sometimes that method isn't actually overriding the real method, particularly when including an abstract module where that method had been defined as abstract: in that case, we'd still be calling the final method. This meant that certain patterns would have had surprising runtime failures despite being accepted statically. For example, this would fail at runtime:

# typed: true

class Parent
  sig(:final) { void }
  def foo = puts 'Hello!'
end

module IFoo
  extend T::Helpers
  abstract!

  sig { abstract.void }
  def foo; end
end

class Child < Parent
  include IFoo # <- suceeds statically, fails at runtime
end

-> sorbet.run link

With this change, the above succeeds.

Test plan

See included automated tests. Added tests to exercise this case and show that it only happens when the "override" is happening from an abstract method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant