diff --git a/spec/compiler/semantic/restrictions_spec.cr b/spec/compiler/semantic/restrictions_spec.cr index cfbb65e7b9c1..aac752c0ae1e 100644 --- a/spec/compiler/semantic/restrictions_spec.cr +++ b/spec/compiler/semantic/restrictions_spec.cr @@ -63,6 +63,36 @@ describe "Restrictions" do end describe "restriction_of?" do + describe "Metaclass vs Metaclass-with-free-vars" do + it "inserts Metaclass before Metaclass-with-free-vars" do + assert_type(%( + def foo(a : T.class) forall T + 1 + end + + def foo(a : Int32.class) + true + end + + foo(Int32) + )) { bool } + end + + it "keeps Metaclass before Metaclass-with-free-vars" do + assert_type(%( + def foo(a : Int32.class) + true + end + + def foo(a : T.class) forall T + 1 + end + + foo(Int32) + )) { bool } + end + end + describe "GenericClassType vs GenericClassInstanceType" do it "inserts GenericClassInstanceType before GenericClassType" do assert_type(%( diff --git a/src/compiler/crystal/semantic/restrictions.cr b/src/compiler/crystal/semantic/restrictions.cr index 221d0c8b95ac..78c3840e8803 100644 --- a/src/compiler/crystal/semantic/restrictions.cr +++ b/src/compiler/crystal/semantic/restrictions.cr @@ -346,8 +346,19 @@ module Crystal other_type = owner.lookup_type?(other) if self_type && other_type self_type.restriction_of?(other_type, owner) + elsif self_type + # `other` cannot resolve to a type, it's probably a free variable like: + # + # ``` + # def foo(param : T.class) forall T + # end + # + # def foo(param : Int32.class) + # end + # ``` + true else - self == other + false end end end