From 7ac9ce5b5125f97fa7462d6c5da3a3a3ec9ae15c Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Fri, 17 Aug 2018 12:28:50 -0300 Subject: [PATCH] Make self to be eager evaluated --- spec/compiler/semantic/module_spec.cr | 25 +++++++++++-------- src/compiler/crystal/macros/interpreter.cr | 3 --- src/compiler/crystal/semantic/main_visitor.cr | 2 -- .../crystal/semantic/semantic_visitor.cr | 2 -- .../crystal/semantic/top_level_visitor.cr | 2 +- src/compiler/crystal/semantic/type_lookup.cr | 21 ++++++---------- src/enum.cr | 5 ++++ 7 files changed, 27 insertions(+), 33 deletions(-) diff --git a/spec/compiler/semantic/module_spec.cr b/spec/compiler/semantic/module_spec.cr index 1948f16bafd0..085e005201c8 100644 --- a/spec/compiler/semantic/module_spec.cr +++ b/spec/compiler/semantic/module_spec.cr @@ -250,7 +250,7 @@ describe "Semantic: module" do end Baz.new.foo - ") { types["Baz"].metaclass } + ") { generic_class("Bar", int32).metaclass } end it "includes generic module with self (check argument type, success)" do @@ -303,15 +303,15 @@ describe "Semantic: module" do class Baz1 < Bar(Int32) end - class Baz2 < Bar(Int32) + class Baz2 < Bar(Float64) end Baz1.new.foo Baz2.new ", "no overload matches" end - it "includes generic module with self (check argument superclass type, error)" do - assert_error " + it "includes generic module with self (check argument superclass type, success)" do + assert_type(" module Foo(T) def foo(x : T) x @@ -322,11 +322,14 @@ describe "Semantic: module" do include Foo(self) end - class Baz < Bar(Int32) + class Baz1 < Bar(Int32) end - Baz.new.foo Bar(Int32).new - ", "no overload matches" + class Baz2 < Bar(Int32) + end + + Baz1.new.foo Baz2.new + ") { types["Baz2"] } end it "includes generic module with self (check return type, success)" do @@ -376,11 +379,11 @@ describe "Semantic: module" do include Foo(self) end - class Baz < Bar(Int32) + class Baz < Bar(Float64) end Baz.new.foo - ", "type must be Baz, not Bar(Int32)" + ", "type must be Bar(Float64), not Bar(Int32)" end it "includes generic module with self (check return subclass type, error)" do @@ -398,11 +401,11 @@ describe "Semantic: module" do class Baz1 < Bar(Int32) end - class Baz2 < Bar(Int32) + class Baz2 < Bar(Float64) end Baz1.new.foo - ", "type must be Baz1, not Baz2" + ", "type must be Bar(Int32), not Baz2" end it "includes module but can't access metaclass methods" do diff --git a/src/compiler/crystal/macros/interpreter.cr b/src/compiler/crystal/macros/interpreter.cr index 466b3a0d5e62..09ced3441ffe 100644 --- a/src/compiler/crystal/macros/interpreter.cr +++ b/src/compiler/crystal/macros/interpreter.cr @@ -456,9 +456,6 @@ module Crystal end TypeNode.new(matched_type) - when Self - target = @scope == @program.class_type ? @scope : @scope.instance_type - TypeNode.new(target) when ASTNode matched_type else diff --git a/src/compiler/crystal/semantic/main_visitor.cr b/src/compiler/crystal/semantic/main_visitor.cr index 50e66ab9dae5..58e809c3de2a 100644 --- a/src/compiler/crystal/semantic/main_visitor.cr +++ b/src/compiler/crystal/semantic/main_visitor.cr @@ -218,8 +218,6 @@ module Crystal # It's different if from a virtual type we do `v.class.new` # because the class could be any in the hierarchy. node.type = check_type_in_type_args(type.remove_alias_if_simple).devirtualize - when Self - node.type = check_type_in_type_args(the_self(node).remove_alias_if_simple) when ASTNode type.accept self unless type.type? node.syntax_replacement = type diff --git a/src/compiler/crystal/semantic/semantic_visitor.cr b/src/compiler/crystal/semantic/semantic_visitor.cr index 06f90d7a079b..76952095e0c9 100644 --- a/src/compiler/crystal/semantic/semantic_visitor.cr +++ b/src/compiler/crystal/semantic/semantic_visitor.cr @@ -238,13 +238,11 @@ abstract class Crystal::SemanticVisitor < Crystal::Visitor def lookup_type(node : ASTNode, free_vars = nil, - lazy_self = false, find_root_generic_type_parameters = true) current_type.lookup_type( node, free_vars: free_vars, allow_typeof: false, - lazy_self: lazy_self, find_root_generic_type_parameters: find_root_generic_type_parameters ) end diff --git a/src/compiler/crystal/semantic/top_level_visitor.cr b/src/compiler/crystal/semantic/top_level_visitor.cr index 903398576c50..7ea5973cc759 100644 --- a/src/compiler/crystal/semantic/top_level_visitor.cr +++ b/src/compiler/crystal/semantic/top_level_visitor.cr @@ -944,7 +944,7 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor def include_in(current_type, node, kind) node_name = node.name - type = lookup_type(node_name, lazy_self: true) + type = lookup_type(node_name) case type when GenericModuleType node.raise "wrong number of type vars for #{type} (given 0, expected #{type.type_vars.size})" diff --git a/src/compiler/crystal/semantic/type_lookup.cr b/src/compiler/crystal/semantic/type_lookup.cr index 892547d959e7..bbaf9c103789 100644 --- a/src/compiler/crystal/semantic/type_lookup.cr +++ b/src/compiler/crystal/semantic/type_lookup.cr @@ -41,28 +41,28 @@ class Crystal::Type # ``` # # If `self` is `Foo` and `Bar(Baz)` is given, the result will be `Foo::Bar(Baz)`. - def lookup_type(node : ASTNode, self_type = self.instance_type, allow_typeof = true, lazy_self = false, free_vars : Hash(String, TypeVar)? = nil, find_root_generic_type_parameters = true) : Type - TypeLookup.new(self, self_type, true, allow_typeof, lazy_self, free_vars, find_root_generic_type_parameters).lookup(node).not_nil! + def lookup_type(node : ASTNode, self_type = self.instance_type, allow_typeof = true, free_vars : Hash(String, TypeVar)? = nil, find_root_generic_type_parameters = true) : Type + TypeLookup.new(self, self_type, true, allow_typeof, free_vars, find_root_generic_type_parameters).lookup(node).not_nil! end # Similar to `lookup_type`, but returns `nil` if a type can't be found. - def lookup_type?(node : ASTNode, self_type = self.instance_type, allow_typeof = true, lazy_self = false, free_vars : Hash(String, TypeVar)? = nil, find_root_generic_type_parameters = true) : Type? - TypeLookup.new(self, self_type, false, allow_typeof, lazy_self, free_vars, find_root_generic_type_parameters).lookup(node) + def lookup_type?(node : ASTNode, self_type = self.instance_type, allow_typeof = true, free_vars : Hash(String, TypeVar)? = nil, find_root_generic_type_parameters = true) : Type? + TypeLookup.new(self, self_type, false, allow_typeof, free_vars, find_root_generic_type_parameters).lookup(node) end # 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, 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! + TypeLookup.new(self, self.instance_type, true, 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, 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) + TypeLookup.new(self, self.instance_type, raise, false, free_vars, find_root_generic_type_parameters).lookup_type_var?(node) end private struct TypeLookup - def initialize(@root : Type, @self_type : Type, @raise : Bool, @allow_typeof : Bool, @lazy_self : Bool, @free_vars : Hash(String, TypeVar)? = nil, @find_root_generic_type_parameters = true) + def initialize(@root : Type, @self_type : Type, @raise : Bool, @allow_typeof : Bool, @free_vars : Hash(String, TypeVar)? = nil, @find_root_generic_type_parameters = true) @in_generic_args = 0 # If we are looking types inside a non-instantiated generic type, @@ -91,8 +91,6 @@ class Crystal::Type end when Type return type_var - when Self - return lookup(type_var) end if @raise @@ -220,11 +218,6 @@ class Crystal::Type type_vars = Array(TypeVar).new(node.type_vars.size + 1) node.type_vars.each do |type_var| case type_var - when Self - if @lazy_self - type_vars << type_var - next - end when NumberLiteral type_vars << type_var next diff --git a/src/enum.cr b/src/enum.cr index b142fc4e3df6..39cafa164fd1 100644 --- a/src/enum.cr +++ b/src/enum.cr @@ -237,6 +237,11 @@ struct Enum value <=> other.value end + # :nodoc: + def ==(other) + false + end + # Returns `true` if this enum member's value includes *other*. This # performs a logical "and" between this enum member's value and *other*'s, # so instead of writing: