Skip to content

Commit

Permalink
Disallow duplicate free variables in defs (#11965)
Browse files Browse the repository at this point in the history
Makes the following a syntax error:

```crystal
def foo(x : T) forall T, T # Error: duplicated free variable name: T
end
```

Currently the two `T`s are indistinguishable, but if something like #11908 is eventually implemented, the same free variable might be bounded in one place but not another (`T <= Int32, T`), or it might have two different bounds (`T <= Int32, T <= String`). This PR ensures every name to the right of `forall` defines a distinct free variable.
  • Loading branch information
HertzDevil committed Apr 28, 2022
1 parent 1d0ccf2 commit 60f17f5
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 1 deletion.
1 change: 1 addition & 0 deletions spec/compiler/parser/parser_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ module Crystal
it_parses "def foo(x : U) : Int32 forall T, U; end", Def.new("foo", args: [Arg.new("x", restriction: "U".path)], return_type: "Int32".path, free_vars: %w(T U))
assert_syntax_error "def foo(x : U) forall; end"
assert_syntax_error "def foo(x : U) forall U,; end"
assert_syntax_error "def foo(x : U) forall U, U; end", "duplicated free variable name: U"

it_parses "foo", "foo".call
it_parses "foo()", "foo".call
Expand Down
4 changes: 3 additions & 1 deletion src/compiler/crystal/syntax/parser.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3685,7 +3685,9 @@ module Crystal
free_vars = [] of String
while true
check :CONST
free_vars << @token.value.to_s
free_var = @token.value.to_s
raise "duplicated free variable name: #{free_var}", @token if free_vars.includes?(free_var)
free_vars << free_var

next_token_skip_space
if @token.type.op_comma?
Expand Down

0 comments on commit 60f17f5

Please sign in to comment.