Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions spec/compiler/interpreter/bugs_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -237,5 +237,26 @@ describe Crystal::Repl::Interpreter do
typeof(foo) == Foo
CRYSTAL
end

it "looks up local vars in parent scopes after looking up local vars in current scope and closured scope (#15489)" do
interpret(<<-CRYSTAL).should eq("parser")
def capture(&block)
block
end

def scoped(&)
yield 1
end

scoped do |parser|
capture do
parser
end
parser # Error: BUG: missing downcast_distinct from String to Int32 (Crystal::NonGenericClassType to Crystal::IntegerType)
end

parser = "parser"
CRYSTAL
end
end
end
22 changes: 11 additions & 11 deletions src/compiler/crystal/interpreter/compiler.cr
Original file line number Diff line number Diff line change
Expand Up @@ -791,28 +791,28 @@ class Crystal::Repl::Compiler < Crystal::Visitor
end

def lookup_local_var_or_closured_var(name : String) : LocalVar | ClosuredVar
lookup_local_var?(name) ||
lookup_local_var?(name, at: @block_level) ||
lookup_closured_var?(name) ||
lookup_local_var?(name, from: @block_level - 1) ||
raise("BUG: can't find closured var or local var #{name}")
end

def lookup_local_var(name : String) : LocalVar
lookup_local_var?(name) || raise("BUG: can't find local var #{name}")
end

def lookup_local_var?(name : String) : LocalVar?
block_level = @block_level
while block_level >= 0
index = @local_vars.name_to_index?(name, block_level)
if index
type = @local_vars.type(name, block_level)
return LocalVar.new(index, type)
def lookup_local_var?(name : String, *, from : Int32 = @block_level) : LocalVar?
from.downto(0) do |block_level|
if local_var = lookup_local_var?(name, at: block_level)
return local_var
end

block_level -= 1
end
end

nil
def lookup_local_var?(name : String, *, at block_level : Int32) : LocalVar?
if index = @local_vars.name_to_index?(name, block_level)
LocalVar.new(index, @local_vars.type(name, block_level))
end
end

def lookup_closured_var(name : String) : ClosuredVar
Expand Down