Remove support for extending traits

Now that the Ruby compiler defines types using multiple passes, there no
longer is a need for forward declaring and extending traits. Extending
traits could also lead to odd behaviour when adding default methods. For
example:

    trait A {}

    object Foo {}

    impl A for Foo {}

    trait A {
      def thing -> Integer {
        10
      }
    }

Here type "Foo" would not have access to method "thing", because it is
added after "A" is implemented for "Foo".

Removing support for this entirely solves this problem, and we no longer
need it anyway.
parent 9f152024
Pipeline #106692438 passed with stages
in 49 minutes and 45 seconds
......@@ -10,7 +10,7 @@ module Inkoc
attr_reader :name, :type_parameters, :body, :location,
:required_traits
attr_accessor :block_type, :redefines
attr_accessor :block_type
# name - The name of the trait.
# targs - The type arguments of the trait.
......@@ -25,7 +25,6 @@ module Inkoc
@body = body
@location = location
@block_type = nil
@redefines = false
end
def visitor_method
......
......@@ -319,17 +319,6 @@ module Inkoc
)
end
def extend_trait_error(type, location)
tname = type.type_name
error(
"The trait #{tname} can not be extended because it is not empty",
location
)
TypeSystem::Error.new
end
def dereference_error(type, location)
tname = type.type_name
......
......@@ -499,28 +499,11 @@ module Inkoc
end
def on_trait(node, scope)
return extend_trait(node.type, node, scope) if node.redefines
body_scope = scope_for_object_body(node)
define_type(node.body, body_scope)
end
def extend_trait(trait, node, scope)
body_type = TypeSystem::Block.closure(typedb.block_type)
body_scope = TypeScope
.new(trait, body_type, @module, locals: node.body.locals)
body_scope.define_receiver_type
node.block_type = body_type
define_type(node.body, body_scope)
trait
end
def on_reopen_object(node, scope)
type = on_type_name_reference(node.name, scope)
......
......@@ -24,7 +24,8 @@ module Inkoc
def on_trait(node, scope)
if (existing = scope.lookup_type(node.name))
return extend_trait(existing, node, scope)
return diagnostics
.redefine_existing_constant_error(existing, node.location)
end
type = typedb.new_trait_type(node.name)
......@@ -34,20 +35,6 @@ module Inkoc
define_named_type(node, type, scope)
end
def extend_trait(trait, node, scope)
unless trait.empty?
return diagnostics.extend_trait_error(trait, node.location)
end
return TypeSystem::Error.new unless same_type_parameters?(node, trait)
node.redefines = true
define_required_traits(node, trait, scope)
trait
end
def on_define_type_parameter(node, scope)
traits = define_types(node.required_traits, scope)
......
......@@ -383,11 +383,7 @@ module Inkoc
end
def on_trait(node, body)
if node.redefines
redefine_trait(node, body)
else
define_object(node, body, Config::TRAIT_CONST)
end
define_object(node, body, Config::TRAIT_CONST)
end
def redefine_trait(node, body)
......
......@@ -1836,34 +1836,6 @@ describe Inkoc::Pass::DefineType do
expect(type.implements_trait?(to_string, state)).to eq(true)
end
it 'supports extending of an existing empty trait' do
to_string = state.typedb.new_trait_type('ToString')
inspect = state.typedb.new_trait_type('Inspect')
type_scope.self_type.define_attribute(inspect.name, inspect)
type_scope.self_type.define_attribute(to_string.name, to_string)
type = expression_type('trait Inspect: ToString { def inspect {} }')
expect(type).to eq(inspect)
expect(inspect.implements_trait?(to_string, state)).to eq(true)
expect(inspect.attributes['inspect']).to be_any
end
it 'does not redefine type parameters when extending an existing trait' do
inspect = state.typedb.new_trait_type('Inspect')
inspect.define_type_parameter('T')
type_scope.self_type.define_attribute(inspect.name, inspect)
type = expression_type('trait Inspect!(T) { def inspect }')
expect(type).to eq(inspect)
expect(type.type_parameters.length).to eq(1)
end
it 'errors when extending a non-empty trait' do
to_string = state.typedb.new_trait_type('ToString')
inspect = state.typedb.new_trait_type('Inspect')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment