Skip to content

Commit

Permalink
Merge pull request #3294 from crystal-lang/feature/relax_type_vars
Browse files Browse the repository at this point in the history
Lift the restriction that type variables can only be single letter names
Ary Borenszweig authored Sep 13, 2016

Verified

This commit was signed with the committer’s verified signature.
wyattjoh Wyatt Johnson
2 parents 9ed020d + 7e08ee1 commit 5f372c1
Showing 5 changed files with 33 additions and 13 deletions.
4 changes: 1 addition & 3 deletions spec/compiler/parser/parser_spec.cr
Original file line number Diff line number Diff line change
@@ -420,6 +420,7 @@ describe "Parser" do
it_parses "class Foo < Bar; end", ClassDef.new("Foo".path, superclass: "Bar".path)
it_parses "class Foo(T); end", ClassDef.new("Foo".path, type_vars: ["T"])
it_parses "class Foo(T1); end", ClassDef.new("Foo".path, type_vars: ["T1"])
it_parses "class Foo(Type); end", ClassDef.new("Foo".path, type_vars: ["Type"])
it_parses "abstract class Foo; end", ClassDef.new("Foo".path, abstract: true)
it_parses "abstract struct Foo; end", ClassDef.new("Foo".path, abstract: true, struct: true)

@@ -1329,9 +1330,6 @@ describe "Parser" do

assert_syntax_error "macro foo(x : Int32); end"

assert_syntax_error "class Foo(Something); end", "type variables can only be single letters"
assert_syntax_error "module Foo(Something); end", "type variables can only be single letters"

assert_syntax_error "/foo)/", "invalid regex"
assert_syntax_error "def =\nend"
assert_syntax_error "def foo; A = 1; end", "dynamic constant assignment"
11 changes: 11 additions & 0 deletions spec/compiler/semantic/restrictions_spec.cr
Original file line number Diff line number Diff line change
@@ -370,4 +370,15 @@ describe "Restrictions" do
Foo.new { nil.as(Rec)}.t
)) { types["Rec"].metaclass }
end

it "matches free variable for type variable" do
assert_type(%(
class Foo(Type)
def initialize(x : Type)
end
end
Foo.new(1)
)) { generic_class "Foo", int32 }
end
end
12 changes: 8 additions & 4 deletions src/compiler/crystal/semantic/restrictions.cr
Original file line number Diff line number Diff line change
@@ -368,8 +368,11 @@ module Crystal
return restrict ident_type, context
end

if single_name && Parser.free_var_name?(other.names.first)
return context.set_free_var(other.names.first, self)
if single_name
first_name = other.names.first
if context.defining_type.type_var?(first_name) || Parser.free_var_name?(first_name)
return context.set_free_var(first_name, self)
end
end

if had_ident_type
@@ -830,8 +833,9 @@ module Crystal
else
single_name = other.names.size == 1
if single_name
if Parser.free_var_name?(other.names.first)
return context.set_free_var(other.names.first, self)
first_name = other.names.first
if context.defining_type.type_var?(first_name) || Parser.free_var_name?(first_name)
return context.set_free_var(first_name, self)
else
other.raise_undefined_constant(context.defining_type)
end
4 changes: 0 additions & 4 deletions src/compiler/crystal/syntax/parser.cr
Original file line number Diff line number Diff line change
@@ -1582,10 +1582,6 @@ module Crystal
end
type_var_name = check_const

unless Parser.free_var_name?(type_var_name)
raise "type variables can only be single letters optionally followed by a digit", @token
end

if type_vars.includes? type_var_name
raise "duplicated type var name: #{type_var_name}", @token
end
15 changes: 13 additions & 2 deletions src/compiler/crystal/types.cr
Original file line number Diff line number Diff line change
@@ -528,6 +528,11 @@ module Crystal
def private=(set_private)
end

# Returns true if *name* if an unbound type variable in this (generic) type.
def type_var?(name)
false
end

def inspect(io)
to_s(io)
end
@@ -1262,6 +1267,10 @@ module Crystal
end
superclass
end

def type_var?(name)
type_vars.includes? name
end
end

# An un-bound type parameter of a generic type.
@@ -2338,7 +2347,8 @@ module Crystal
program.class_type
end

delegate abstract?, generic_nest, lookup_new_in_ancestors?, to: instance_type
delegate abstract?, generic_nest, lookup_new_in_ancestors?,
type_var?, to: instance_type

def class_var_owner
instance_type
@@ -2732,7 +2742,8 @@ module Crystal
delegate leaf?, superclass, lookup_first_def, lookup_defs,
lookup_defs_with_modules, lookup_instance_var, lookup_instance_var?,
index_of_instance_var, lookup_macro, lookup_macros, all_instance_vars,
abstract?, implements?, covariant?, ancestors, struct?, to: base_type
abstract?, implements?, covariant?, ancestors, struct?,
type_var?, to: base_type

def remove_indirection
if struct?

0 comments on commit 5f372c1

Please sign in to comment.