Skip to content

Commit

Permalink
Detect recursive generic structs (#5099)
Browse files Browse the repository at this point in the history
* Detect recursive generic struct through module

* Detect recursive generic struct through generic module
  • Loading branch information
iSarCasm authored and RX14 committed Oct 11, 2017
1 parent 2637f83 commit 4d872f9
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 2 deletions.
28 changes: 28 additions & 0 deletions spec/compiler/semantic/struct_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,34 @@ describe "Semantic: struct" do
"recursive struct Foo detected: `@moo : Moo` -> `Moo` -> `Foo`"
end

it "detects recursive generic struct through module (#4720)" do
assert_error %(
module Bar
end
struct Foo(T)
include Bar
def initialize(@base : Bar?)
end
end
),
"recursive struct Foo(T) detected: `@base : (Bar | Nil)` -> `Bar` -> `Foo(T)`"
end

it "detects recursive generic struct through generic module (#4720)" do
assert_error %(
module Bar(T)
end
struct Foo(T)
include Bar(T)
def initialize(@base : Bar(T)?)
end
end
),
"recursive struct Foo(T) detected: `@base : (Bar(T) | Nil)` -> `Bar(T)` -> `Foo(T)`"
end

it "detects recursive struct through inheritance (#3071)" do
assert_error %(
abstract struct Foo
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/crystal/semantic/recursive_struct_checker.cr
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class Crystal::RecursiveStructChecker
end
end

if type.is_a?(NonGenericModuleType)
if type.is_a?(NonGenericModuleType) || type.is_a?(GenericModuleInstanceType)
path.push type
# Check if the module is composed, recursively, of the target struct
type.raw_including_types.try &.each do |module_type|
Expand Down Expand Up @@ -140,6 +140,6 @@ class Crystal::RecursiveStructChecker
end

def struct?(type)
type.struct? && type.is_a?(InstanceVarContainer) && !type.is_a?(PrimitiveType) && !type.is_a?(ProcInstanceType) && !type.is_a?(GenericClassType) && !type.abstract?
type.struct? && type.is_a?(InstanceVarContainer) && !type.is_a?(PrimitiveType) && !type.is_a?(ProcInstanceType) && !type.abstract?
end
end

0 comments on commit 4d872f9

Please sign in to comment.