Skip to content

Commit

Permalink
Don't find unbound type parameter in main code inside generic type (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite authored and RX14 committed Jun 29, 2018
1 parent bfd9e6d commit 2bbf72f
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 5 deletions.
9 changes: 9 additions & 0 deletions spec/compiler/semantic/generic_class_spec.cr
Expand Up @@ -1054,4 +1054,13 @@ describe "Semantic: generic class" do
),
"undefined constant "
end

it "doesn't find unbound type parameter in main code inside generic type (#6168)" do
assert_error %(
class Foo(T)
Foo(T)
end
),
"undefined constant T"
end
end
15 changes: 14 additions & 1 deletion src/compiler/crystal/semantic/main_visitor.cr
Expand Up @@ -170,7 +170,20 @@ module Crystal
end

def visit(node : Path)
type = (@path_lookup || @scope || @current_type).lookup_type_var(node, free_vars: free_vars)
lookup_scope = @path_lookup || @scope || @current_type

# If the lookup scope is a generic type, like Foo(T), we don't
# want to find T in main code. For example:
#
# class Foo(T)
# Bar(T) # This T is unbound and it shouldn't be found in the lookup
# end
find_root_generic_type_parameters = !lookup_scope.is_a?(GenericType)

type = lookup_scope.lookup_type_var(node,
free_vars: free_vars,
find_root_generic_type_parameters: find_root_generic_type_parameters)

case type
when Const
if !type.value.type? && !type.visited?
Expand Down
8 changes: 4 additions & 4 deletions src/compiler/crystal/semantic/type_lookup.cr
Expand Up @@ -52,13 +52,13 @@ class Crystal::Type

# Similar to `lookup_type`, but the result might also be an ASTNode, for example when
# looking `N` relative to a StaticArray.
def lookup_type_var(node : Path, free_vars : Hash(String, TypeVar)? = nil) : Type | ASTNode
TypeLookup.new(self, self.instance_type, true, false, false, free_vars).lookup_type_var(node).not_nil!
def lookup_type_var(node : Path, free_vars : Hash(String, TypeVar)? = nil, find_root_generic_type_parameters = true) : Type | ASTNode
TypeLookup.new(self, self.instance_type, true, false, false, free_vars, find_root_generic_type_parameters).lookup_type_var(node).not_nil!
end

# Similar to `lookup_type_var`, but might return `nil`.
def lookup_type_var?(node : Path, free_vars : Hash(String, TypeVar)? = nil, raise = false) : Type | ASTNode | Nil
TypeLookup.new(self, self.instance_type, raise, false, false, free_vars).lookup_type_var?(node)
def lookup_type_var?(node : Path, free_vars : Hash(String, TypeVar)? = nil, raise = false, find_root_generic_type_parameters = true) : Type | ASTNode | Nil
TypeLookup.new(self, self.instance_type, raise, false, false, free_vars, find_root_generic_type_parameters).lookup_type_var?(node)
end

private struct TypeLookup
Expand Down

0 comments on commit 2bbf72f

Please sign in to comment.