Skip to content

Commit 991e39b

Browse files
author
Ary Borenszweig
committedDec 23, 2016
Compiler: require free vars to be specified with forall
1 parent 352d5f0 commit 991e39b

File tree

5 files changed

+16
-9
lines changed

5 files changed

+16
-9
lines changed
 

Diff for: ‎spec/compiler/semantic/restrictions_spec.cr

+11
Original file line numberDiff line numberDiff line change
@@ -407,4 +407,15 @@ describe "Restrictions" do
407407
),
408408
"no overload matches"
409409
end
410+
411+
it "errors if using free var without forall" do
412+
assert_error %(
413+
def foo(x : T)
414+
T
415+
end
416+
417+
foo(1)
418+
),
419+
"undefined constant T"
420+
end
410421
end

Diff for: ‎src/compiler/crystal/semantic/default_arguments.cr

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class Crystal::Def
128128
# a temporary variable (tmp_var) and then replace all ocurrences of that free var with typeof(tmp_var)
129129
# to achieve the same effect, since we can't define a type alias inside a method.
130130
restriction = arg.restriction
131-
if restriction.is_a?(Path) && restriction.names.size == 1 && (Parser.free_var_name?(restriction.names.first) || free_vars.try(&.includes?(restriction.names.first)))
131+
if restriction.is_a?(Path) && restriction.names.size == 1 && free_vars.try(&.includes?(restriction.names.first))
132132
restriction_name = program.new_temp_var_name
133133
new_body << Assign.new(Var.new(restriction_name), Var.new(arg.name))
134134
body = body.transform(ReplaceFreeVarTransformer.new(restriction.names.first, restriction_name))

Diff for: ‎src/compiler/crystal/semantic/restrictions.cr

+2-2
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ module Crystal
377377

378378
if single_name
379379
first_name = other.names.first
380-
if context.defining_type.type_var?(first_name) || Parser.free_var_name?(first_name)
380+
if context.defining_type.type_var?(first_name)
381381
return context.set_free_var(first_name, self)
382382
end
383383
end
@@ -856,7 +856,7 @@ module Crystal
856856
single_name = other.names.size == 1
857857
if single_name
858858
first_name = other.names.first
859-
if context.defining_type.type_var?(first_name) || Parser.free_var_name?(first_name)
859+
if context.defining_type.type_var?(first_name)
860860
return context.set_free_var(first_name, self)
861861
else
862862
other.raise_undefined_constant(context.defining_type)

Diff for: ‎src/compiler/crystal/syntax/parser.cr

-4
Original file line numberDiff line numberDiff line change
@@ -5359,9 +5359,5 @@ module Crystal
53595359
@visibility = old_visibility
53605360
value
53615361
end
5362-
5363-
def self.free_var_name?(name)
5364-
name.size == 1 || (name.size == 2 && name[1].ascii_number?)
5365-
end
53665362
end
53675363
end

Diff for: ‎src/enumerable.cr

+2-2
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ module Enumerable(T)
9191
# * `Enumerable::Chunk::Alone` specifies that the element should be chunked by itself
9292
#
9393
# See also: `Iterator#chunk`
94-
def chunks(&block : T -> U)
94+
def chunks(&block : T -> U) forall U
9595
res = [] of Tuple(U, Array(T))
9696
chunks_internal(block) { |k, v| res << {k, v} }
9797
res
@@ -160,7 +160,7 @@ module Enumerable(T)
160160
end
161161
end
162162

163-
private def chunks_internal(original_block : T -> U)
163+
private def chunks_internal(original_block : T -> U) forall U
164164
acc = Chunk::Accumulator(T, U).new
165165
each do |val|
166166
key = original_block.call(val)

0 commit comments

Comments
 (0)
Please sign in to comment.