Skip to content

Commit

Permalink
Showing 5 changed files with 44 additions and 7 deletions.
18 changes: 18 additions & 0 deletions spec/compiler/codegen/uninitialized_spec.cr
Original file line number Diff line number Diff line change
@@ -87,4 +87,22 @@ describe "Code gen: uninitialized" do
a
)).to_i.should eq(3)
end

it "works with uninitialized NoReturn (#3314)" do
codegen(%(
def foo
x = uninitialized NoReturn
if 1
x = yield
end
x
end
def bar
foo { return }
end
bar
), inject_primitives: false)
end
end
14 changes: 14 additions & 0 deletions spec/compiler/semantic/uninitialized_spec.cr
Original file line number Diff line number Diff line change
@@ -112,4 +112,18 @@ describe "Semantic: uninitialized" do
"use a more specific type"
end
end

it "works with uninitialized NoReturn (#3314)" do
assert_type(%(
def foo
x = uninitialized typeof(yield)
end
def bar
foo { return }
end
bar
)) { nil_type }
end
end
4 changes: 2 additions & 2 deletions spec/spec_helper.cr
Original file line number Diff line number Diff line change
@@ -273,8 +273,8 @@ def parse(string, wants_doc = false)
parser.parse
end

def codegen(code)
code = inject_primitives(code)
def codegen(code, inject_primitives = true)
code = inject_primitives(code) if inject_primitives
node = parse code
result = semantic node
result.program.codegen result.node, single_module: false
6 changes: 3 additions & 3 deletions src/compiler/crystal/codegen/codegen.cr
Original file line number Diff line number Diff line change
@@ -1032,6 +1032,8 @@ module Crystal
def visit(node : Var)
var = context.vars[node.name]?
if var
return unreachable if var.type.no_return?

# Special variables always have an extra pointer
already_loaded = (node.special_var? ? false : var.already_loaded)
@last = downcast var.pointer, node.type, var.type, already_loaded
@@ -1220,9 +1222,7 @@ module Crystal
end

def declare_var(var)
return if var.no_returns?

context.vars[var.name] ||= LLVMVar.new(alloca(llvm_type(var.type), var.name), var.type)
context.vars[var.name] ||= LLVMVar.new(var.no_returns? ? llvm_nil : alloca(llvm_type(var.type), var.name), var.type)
end

def declare_lib_var(name, type, thread_local)
9 changes: 7 additions & 2 deletions src/compiler/crystal/semantic/main_visitor.cr
Original file line number Diff line number Diff line change
@@ -374,8 +374,13 @@ module Crystal
node.declared_type.accept self
@in_type_args -= 1

var_type = check_declare_var_type node, node.declared_type.type, "a variable"
var.type = var_type
# TOOD: should we be using a binding here to recompute the type?
if declared_type = node.declared_type.type?
var_type = check_declare_var_type node, declared_type, "a variable"
var.type = var_type
else
var.type = program.no_return
end

meta_var = @meta_vars[var.name] ||= new_meta_var(var.name)
if (existing_type = meta_var.type?) && existing_type != var_type

0 comments on commit f0bacbc

Please sign in to comment.