Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d5fe700ee0df
Choose a base ref
...
head repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 66f431240b3e
Choose a head ref
  • 3 commits
  • 12 files changed
  • 1 contributor

Commits on May 30, 2016

  1. Copy the full SHA
    67844e0 View commit details
  2. Spec: better abort (imeediately quits and prints summary)

    Ary Borenszweig committed May 30, 2016
    Copy the full SHA
    7daab73 View commit details
  3. Compiler: stop tracking whether a type was allocated or not. Fixes #2607

    
    
    Before 0.16.0 we needed to know whether a type was allocated or not because
    if it wasn't we couldn't know the type of its instance variables and so all code
    related to that type couldn't be codegen-ed. After 0.16.0 this is no longer true,
    and code can always be generated, even if a type wasn't instantiated.
    Ary Borenszweig committed May 30, 2016
    Copy the full SHA
    66f4312 View commit details
23 changes: 0 additions & 23 deletions spec/compiler/codegen/cast_spec.cr
Original file line number Diff line number Diff line change
@@ -248,29 +248,6 @@ describe "Code gen: cast" do
)).to_i.should_not eq(0)
end

it "errors if casting to a non-allocated type" do
run(%(
require "prelude"
class Foo
end
class Bar < Foo
end
class Baz < Foo
end
foo = Foo.new || Bar.new
begin
foo as Baz
rescue ex
ex.message.not_nil!.includes?("can't cast to Baz because it was never instantiated")
end
)).to_b.should be_true
end

it "casts (bug)" do
run(%(
require "prelude"
15 changes: 15 additions & 0 deletions spec/compiler/codegen/exception_spec.cr
Original file line number Diff line number Diff line change
@@ -1099,4 +1099,19 @@ describe "Code gen: exception" do
ex.not_nil!.message.to_s
)).to_string.should eq("foo")
end

it "can rescue TypeCastError (#2607)" do
run(%(
require "prelude"
begin
(1 || "foo").as(String)
2
rescue e : TypeCastError
42
rescue e : Exception
0
end
)).to_i.should eq(42)
end
end
25 changes: 0 additions & 25 deletions spec/compiler/codegen/untyped_expression_spec.cr

This file was deleted.

22 changes: 0 additions & 22 deletions spec/compiler/type_inference/macro_spec.cr
Original file line number Diff line number Diff line change
@@ -278,28 +278,6 @@ describe "Type inference: macro" do
)) { types["Bar"] }
end

it "doesn't die on untyped instance var" do
assert_type(%(
require "prelude"
class Foo
def initialize
@foo = 1
end
def foo
@foo
end
def ivars_size : Int32
{{@type.instance_vars.size}}
end
end
->(x : Foo) { x.foo; x.ivars_size }
)) { fun_of(types["Foo"], no_return) }
end

it "errors if non-existent named arg" do
assert_error %(
macro foo(x = 1)
9 changes: 5 additions & 4 deletions src/compiler/crystal/command.cr
Original file line number Diff line number Diff line change
@@ -411,10 +411,9 @@ class Crystal::Command
private def execute(output_filename, run_args)
begin
Process.run(output_filename, args: run_args, input: true, output: true, error: true) do |process|
Signal::INT.trap do
process.kill
exit
end
# Ignore the signal so we don't exit the running process
# (the running process can still handle this signal)
Signal::INT.ignore # do
end
status = $?
ensure
@@ -429,6 +428,8 @@ class Crystal::Command
STDERR.puts "Program was killed"
when Signal::SEGV
STDERR.puts "Program exited because of a segmentation fault (11)"
when Signal::INT
# OK, bubbled from the sub-program
else
STDERR.puts "Program received and didn't handle signal #{status.exit_signal} (#{status.exit_signal.value})"
end
4 changes: 0 additions & 4 deletions src/compiler/crystal/program.cr
Original file line number Diff line number Diff line change
@@ -121,11 +121,9 @@ module Crystal
types["StaticArray"] = static_array = @static_array = StaticArrayType.new self, self, "StaticArray", value, ["T", "N"]
static_array.struct = true
static_array.declare_instance_var("@buffer", Path.new("T"))
static_array.allocated = true
static_array.allowed_in_generics = false

types["String"] = string = @string = NonGenericClassType.new self, self, "String", reference
string.allocated = true

string.declare_instance_var("@bytesize", @int32)
string.declare_instance_var("@length", @int32)
@@ -134,7 +132,6 @@ module Crystal
types["Class"] = klass = @class = MetaclassType.new(self, object, value, "Class")
object.metaclass = klass
klass.metaclass = klass
klass.allocated = true
klass.allowed_in_generics = false

types["Struct"] = struct_t = @struct_t = NonGenericClassType.new self, self, "Struct", value
@@ -507,7 +504,6 @@ module Crystal
private def abstract_value_type(type)
type.abstract = true
type.struct = true
type.allocated = true
type.allowed_in_generics = false
end

91 changes: 21 additions & 70 deletions src/compiler/crystal/semantic/cleanup_transformer.cr
Original file line number Diff line number Diff line change
@@ -323,24 +323,15 @@ module Crystal
block.fun_literal = fun_literal.transform(self)
end

# Check if we have an untyped expression in this call, or an expression
# whose type was never allocated. Replace it with raise.
# Check if we have an untyped expression in this call. Replace it with raise.
if (obj && !obj_type)
return untyped_expression(node, "`#{obj}` has no type")
end

if obj && !obj.type.allocated?
return untyped_expression(node, "#{obj.type} in `#{obj}` was never instantiated")
end

node.args.each do |arg|
unless arg.type?
return untyped_expression(node, "`#{arg}` has no type")
end

unless arg.type.allocated?
return untyped_expression(node, "#{arg.type} in `#{arg}` was never instantiated")
end
end

# Check if the block has its type freezed and it doesn't match the current type
@@ -369,7 +360,6 @@ module Crystal

if target_defs = node.target_defs
changed = false
allocated_defs = [] of Def

if target_defs.size == 1
if target_defs[0].is_a?(External)
@@ -382,45 +372,31 @@ module Crystal
end

target_defs.each do |target_def|
allocated = target_def.owner.allocated? && target_def.args.all? &.type.allocated?
if allocated
allocated_defs << target_def

unless @transformed.includes?(target_def.object_id)
@transformed.add(target_def.object_id)

node.bubbling_exception do
old_body = target_def.body
old_type = target_def.body.type?

@def_nest_count += 1
target_def.body = target_def.body.transform(self)
@def_nest_count -= 1

new_type = target_def.body.type?

# It can happen that the body of the function changed, and as
# a result the type changed. In that case we need to rebind the
# def to the new body, unbinding it from the previous one.
if new_type != old_type
@changed = true
target_def.unbind_from old_body
target_def.bind_to target_def.body
end
unless @transformed.includes?(target_def.object_id)
@transformed.add(target_def.object_id)

node.bubbling_exception do
old_body = target_def.body
old_type = target_def.body.type?

@def_nest_count += 1
target_def.body = target_def.body.transform(self)
@def_nest_count -= 1

new_type = target_def.body.type?

# It can happen that the body of the function changed, and as
# a result the type changed. In that case we need to rebind the
# def to the new body, unbinding it from the previous one.
if new_type != old_type
@changed = true
target_def.unbind_from old_body
target_def.bind_to target_def.body
end
end
else
changed = true
end
end

if changed
@changed = true
node.unbind_from node.target_defs
node.target_defs = allocated_defs
node.bind_to allocated_defs
end

if node.target_defs.not_nil!.empty?
exps = [] of ASTNode
if obj = node.obj
@@ -776,10 +752,6 @@ module Crystal
unless resulting_type
node.raise "can't cast #{obj_type} to #{to_type}"
end

unless to_type.allocated?
return build_raise "can't cast to #{to_type} because it was never instantiated"
end
end

node
@@ -819,27 +791,6 @@ module Crystal
node.else = nil
end

if node_rescues = node.rescues
new_rescues = [] of Rescue

node_rescues.each do |a_rescue|
if !a_rescue.type? || a_rescue.type.allocated?
new_rescues << a_rescue
end
end

if new_rescues.empty?
if node.ensure
node.rescues = nil
else
rebind_node node, node.body
return node.body
end
else
node.rescues = new_rescues
end
end

node
end

6 changes: 1 addition & 5 deletions src/compiler/crystal/semantic/fix_empty_types.cr
Original file line number Diff line number Diff line change
@@ -66,11 +66,7 @@ module Crystal
node.target_defs.try &.each do |target_def|
unless @fixed.includes?(target_def.object_id)
@fixed.add(target_def.object_id)

if !target_def.type? && target_def.owner.allocated?
target_def.type = @mod.no_return
end

target_def.type = @mod.no_return unless target_def.type?
target_def.accept_children self
end
end
1 change: 0 additions & 1 deletion src/compiler/crystal/semantic/main_visitor.cr
Original file line number Diff line number Diff line change
@@ -2010,7 +2010,6 @@ module Crystal
node.raise "can't instantiate abstract #{instance_type.type_desc} #{instance_type}"
end

instance_type.allocated = true
node.type = instance_type
end

Loading