Skip to content

Commit

Permalink
Revert "Compiler: refactor and slightly optimize merging two types (c…
Browse files Browse the repository at this point in the history
…rystal-lang#12436)"

This reverts commit bfc33db.
  • Loading branch information
caspiano committed Nov 1, 2022
1 parent 916adf7 commit 442daae
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 40 deletions.
6 changes: 3 additions & 3 deletions src/compiler/crystal/semantic/type_declaration_processor.cr
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ struct Crystal::TypeDeclarationProcessor
when NonGenericModuleType
type = type_info.type
if nilable_instance_var?(owner, name)
type = Type.merge!(type, @program.nil)
type = Type.merge!([type, @program.nil])
end

# Same as above, only Nil makes no sense
Expand All @@ -423,7 +423,7 @@ struct Crystal::TypeDeclarationProcessor
when GenericClassType
type = type_info.type
if nilable_instance_var?(owner, name)
type = Type.merge!(type, @program.nil)
type = Type.merge!([type, @program.nil])
end

# Same as above, only Nil makes no sense
Expand All @@ -442,7 +442,7 @@ struct Crystal::TypeDeclarationProcessor
when GenericModuleType
type = type_info.type
if nilable_instance_var?(owner, name)
type = Type.merge!(type, @program.nil)
type = Type.merge!([type, @program.nil])
end

declare_meta_type_var(owner.instance_vars, owner, name, type, type_info.location, instance_var: true, annotations: type_info.annotations)
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/crystal/semantic/type_guess_visitor.cr
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ module Crystal
info.add_annotations(annotations) if annotations
vars[name] = info
else
info.type = Type.merge!(info.type, type)
info.type = Type.merge!([info.type, type])
info.outside_def = true if @outside_def
info.add_annotations(annotations) if annotations
vars[name] = info
Expand Down
80 changes: 44 additions & 36 deletions src/compiler/crystal/semantic/type_merge.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,69 +5,77 @@ module Crystal
def type_merge(types : Indexable(Type?)) : Type?
case types.size
when 0
nil
return nil
when 1
types.first
return types.first
when 2
# Merging two types is the most common case, so we optimize it
first, second = types
type_merge(first, second)
did_merge, merged_type = type_merge_two(first, second)
return merged_type if did_merge
else
combined_union_of compact_types(types)
# combined_union_of
end

combined_union_of compact_types(types)
end

def type_merge(nodes : Indexable(ASTNode)) : Type?
case nodes.size
when 0
nil
return nil
when 1
nodes.first.type?
return nodes.first.type?
when 2
# Merging two types is the most common case, so we optimize it
first, second = nodes
type_merge(first.type?, second.type?)
did_merge, merged_type = type_merge_two(first.type?, second.type?)
return merged_type if did_merge
else
combined_union_of compact_types(nodes, &.type?)
# combined_union_of
end
end

def type_merge(first : Type?, second : Type?) : Type?
# Same, so return any of them
return first if first == second

# First is nil, so return second
return second unless first

# Second is nil, so return first
return first unless second
combined_union_of compact_types(nodes, &.type?)
end

# NoReturn is removed from unions
return second if first.no_return?
return first if second.no_return?
def type_merge_two(first, second)
if first == second
# Same, so return any of them
{true, first}
elsif first
if second
# first and second not nil and different
if first.opaque_id > second.opaque_id
first, second = second, first
end

# Check if a non-union type is part of a union type
if !first.is_a?(UnionType) && second.is_a?(UnionType) && second.union_types.includes?(first)
return second
end
if first.nil_type?
if second.is_a?(UnionType) && second.union_types.includes?(first)
return true, second
end
end

if !second.is_a?(UnionType) && first.is_a?(UnionType) && first.union_types.includes?(second)
return first
# puts "#{first} vs. #{second}"
{false, nil}
else
# Second is nil, so return first
{true, first}
end
else
# First is nil, so return second
{true, second}
end

# General case
combined_union_of compact_types({first, second})
end

def type_merge_union_of(types : Array(Type)) : Type?
def type_merge_union_of(types : Array(Type))
union_of compact_types(types)
end

def compact_types(types) : Array(Type)
def compact_types(types)
compact_types(types) { |type| type }
end

def compact_types(objects) : Array(Type)
def compact_types(objects)
all_types = Array(Type).new(objects.size)
objects.each { |obj| add_type all_types, yield(obj) }
all_types.reject! &.no_return? if all_types.size > 1
Expand Down Expand Up @@ -174,12 +182,12 @@ module Crystal
end
end

def self.merge!(types_or_nodes) : Type
def self.merge!(types_or_nodes)
merge(types_or_nodes).not_nil!
end

def self.merge!(type1 : Type, type2 : Type) : Type
type1.program.type_merge(type1, type2).not_nil!
def self.merge!(type1 : Type, type2 : Type)
merge!([type1, type2])
end

# Given two non-union types T and U, returns their least common ancestor
Expand Down

0 comments on commit 442daae

Please sign in to comment.