Skip to content

Commit 50b2254

Browse files
authored
Merge pull request #1152 from ruby/fix-module-inherit
Raise an error if a class definition inherits a module
2 parents adc38f8 + d939368 commit 50b2254

File tree

4 files changed

+60
-1
lines changed

4 files changed

+60
-1
lines changed

lib/rbs/definition_builder/ancestor_builder.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@ def one_instance_ancestors(type_name)
211211
end
212212

213213
NoSuperclassFoundError.check!(super_name, env: env, location: primary.decl.location)
214+
if super_class
215+
InheritModuleError.check!(super_class, env: env)
216+
end
214217

215218
ancestors = OneAncestors.class_instance(
216219
type_name: type_name,
@@ -268,6 +271,9 @@ def one_singleton_ancestors(type_name)
268271
end
269272

270273
NoSuperclassFoundError.check!(super_name, env: env, location: primary.decl.location)
274+
if super_class
275+
InheritModuleError.check!(super_class, env: env)
276+
end
271277

272278
ancestors = OneAncestors.singleton(
273279
type_name: type_name,

lib/rbs/errors.rb

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,27 @@ def initialize(type_name:, location:)
148148
end
149149

150150
def self.check!(type_name, env:, location:)
151-
env.class_decls.key?(type_name) or raise new(type_name: type_name, location: location)
151+
if decl = env.class_decls[type_name]
152+
return
153+
end
154+
155+
raise new(type_name: type_name, location: location)
156+
end
157+
end
158+
159+
class InheritModuleError < DefinitionError
160+
attr_reader :super_decl
161+
162+
def initialize(super_decl)
163+
@super_decl = super_decl
164+
165+
super "#{Location.to_string(super_decl.location)}: Cannot inherit a module: #{super_decl.name}"
166+
end
167+
168+
def self.check!(super_decl, env:)
169+
return if env.class_decls[super_decl.name].is_a?(Environment::ClassEntry)
170+
171+
raise new(super_decl)
152172
end
153173
end
154174

sig/errors.rbs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ module RBS
197197
def location: () -> Location[untyped, untyped]?
198198
end
199199

200+
# MixinClassError is raised if a include/prepend/extend has a class (not a module) to mix-in
201+
#
200202
class MixinClassError < DefinitionError
201203
type member = AST::Members::Include | AST::Members::Prepend | AST::Members::Extend
202204

@@ -212,6 +214,18 @@ module RBS
212214
def mixin_name: () -> String
213215
end
214216

217+
# InheritModuleError is raised if a class definition inherits a module (not a class)
218+
#
219+
class InheritModuleError < DefinitionError
220+
attr_reader super_decl: AST::Declarations::Class::Super
221+
222+
def initialize: (AST::Declarations::Class::Super) -> void
223+
224+
def location: () -> Location[untyped, untyped]?
225+
226+
def self.check!: (AST::Declarations::Class::Super, env: Environment) -> void
227+
end
228+
215229
class RecursiveTypeAliasError < BaseError
216230
attr_reader alias_names: Array[TypeName]
217231
attr_reader location: Location[untyped, untyped]?

test/rbs/definition_builder_test.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2243,4 +2243,23 @@ class Foo
22432243
end
22442244
end
22452245
end
2246+
2247+
def test_class_definition_inheriting_module
2248+
SignatureManager.new do |manager|
2249+
manager.files.merge!(Pathname("foo.rbs") => <<~EOF)
2250+
module Mod
2251+
end
2252+
2253+
class Foo < Mod
2254+
end
2255+
EOF
2256+
2257+
manager.build do |env|
2258+
builder = DefinitionBuilder.new(env: env)
2259+
2260+
assert_raises(RBS::InheritModuleError) { builder.build_instance(type_name("::Foo")) }
2261+
assert_raises(RBS::InheritModuleError) { builder.build_singleton(type_name("::Foo")) }
2262+
end
2263+
end
2264+
end
22462265
end

0 commit comments

Comments
 (0)