Skip to content

Commit 927cd42

Browse files
hanssvghallak
andauthored
Add check for number of type variables in type signature (#512)
* Fix tvar string generation * Add check for number of tvars in a single type signature The number of tvars is limited by serialization (u8) to 255 * Added a comment in CHANGELOG * Docs fixes * Adding docs about the limitation on number of tvars * Limit is 256, not 255 * Update CHANGELOG.md Co-authored-by: Gaith Hallak <[email protected]> --------- Co-authored-by: Gaith Hallak <[email protected]>
1 parent 16308a7 commit 927cd42

File tree

6 files changed

+98
-5
lines changed

6 files changed

+98
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88
### Added
9+
- Added a check for number of type variables in a type signature; it is serialized using 8 bits,
10+
so the upper limit is 256.
911
### Changed
1012
### Removed
1113

docs/sophia_features.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,11 @@ of `A`.
295295
- When a user-defined type `t('a)` is invariant in `'a`, then `t(A)` can never be
296296
a subtype of `t(B)`.
297297

298+
#### Type variable limitation
299+
300+
Because of how FATE represents types as values there is a fixed upper limit (256)
301+
of type variables that can be used in a single type signature.
302+
298303
## Mutable state
299304

300305
Sophia does not have arbitrary mutable state, but only a limited form of state

docs/sophia_syntax.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,11 +267,11 @@ UnOp ::= '-' | '!' | 'bnot'
267267
| Operators | Type
268268
| --- | ---
269269
| `-` `+` `*` `/` `mod` `^` | arithmetic operators
270-
| `!` `&&` `||` | logical operators
270+
| `!` `&&` `\|\|` | logical operators
271271
| `band` `bor` `bxor` `bnot` `<<` `>>` | bitwise operators
272272
| `==` `!=` `<` `>` `=<` `>=` | comparison operators
273273
| `::` `++` | list operators
274-
| `|>` | functional operators
274+
| `\|>` | functional operators
275275

276276
## Operator precedence
277277

@@ -291,5 +291,5 @@ In order of highest to lowest precedence.
291291
| `bxor` | left
292292
| `bor` | left
293293
| `&&` | right
294-
| `||` | right
295-
| `|>` | left
294+
| `\|\|` | right
295+
| `\|>` | left

src/aeso_ast_infer_types.erl

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1760,8 +1760,27 @@ desugar_clauses(Ann, Fun, {type_sig, _, _, _, ArgTypes, RetType}, Clauses) ->
17601760
end.
17611761

17621762
print_typesig({Name, TypeSig}) ->
1763+
assert_tvars(Name, TypeSig),
17631764
?PRINT_TYPES("Inferred ~s : ~s\n", [Name, pp(TypeSig)]).
17641765

1766+
assert_tvars(Name, TS) ->
1767+
TVars = assert_tvars_(TS, #{}),
1768+
case maps:size(TVars) > 256 of
1769+
true ->
1770+
type_error({too_many_tvars, Name, TS});
1771+
false ->
1772+
ok
1773+
end.
1774+
1775+
assert_tvars_({tvar, _, TV}, TVars) ->
1776+
TVars#{TV => ok};
1777+
assert_tvars_(T, TVars) when is_tuple(T) ->
1778+
assert_tvars_(tuple_to_list(T), TVars);
1779+
assert_tvars_(Ts, TVars) when is_list(Ts) ->
1780+
lists:foldl(fun(T, TVars1) -> assert_tvars_(T, TVars1) end, TVars, Ts);
1781+
assert_tvars_(_, TVars) ->
1782+
TVars.
1783+
17651784
arg_type(ArgAnn, {id, Ann, "_"}) ->
17661785
case aeso_syntax:get_ann(origin, Ann, user) of
17671786
system -> fresh_uvar(ArgAnn);
@@ -3389,7 +3408,7 @@ instantiate1(X) ->
33893408
integer_to_tvar(X) when X < 26 ->
33903409
[$a + X];
33913410
integer_to_tvar(X) ->
3392-
[integer_to_tvar(X div 26)] ++ [$a + (X rem 26)].
3411+
integer_to_tvar(X div 26 - 1) ++ [$a + (X rem 26)].
33933412

33943413
%% Warnings
33953414

@@ -3776,6 +3795,9 @@ mk_error({type_decl, _, {id, Pos, Name}, _}) ->
37763795
Msg = io_lib:format("Empty type declarations are not supported. Type `~s` lacks a definition",
37773796
[Name]),
37783797
mk_t_err(pos(Pos), Msg);
3798+
mk_error({too_many_tvars, Name, {type_sig, Pos, _, _, _, _}}) ->
3799+
Msg = io_lib:format("Too many type variables (max 256) in definition of `~s`", [Name]),
3800+
mk_t_err(pos(Pos), Msg);
37793801
mk_error({stateful_not_allowed, Id, Fun}) ->
37803802
Msg = io_lib:format("Cannot reference stateful function `~s` in the definition of non-stateful function `~s`.",
37813803
[pp(Id), pp(Fun)]),

test/aeso_compiler_tests.erl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,6 +1302,10 @@ failing_contracts() ->
13021302
<<?Pos(3,9)
13031303
"The name of the compile-time constant cannot have pattern matching">>
13041304
])
1305+
, ?TYPE_ERROR(too_many_tvars,
1306+
[<<?Pos(2,3)
1307+
"Too many type variables (max 256) in definition of `too_many`">>
1308+
])
13051309
].
13061310

13071311
validation_test_() ->

test/contracts/too_many_tvars.aes

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
contract C =
2+
entrypoint too_many(
3+
(_, _, _, _, _, _, _, _, _, _),
4+
(_, _, _, _, _, _, _, _, _, _),
5+
(_, _, _, _, _, _, _, _, _, _),
6+
(_, _, _, _, _, _, _, _, _, _),
7+
(_, _, _, _, _, _, _, _, _, _),
8+
(_, _, _, _, _, _, _, _, _, _),
9+
(_, _, _, _, _, _, _, _, _, _),
10+
(_, _, _, _, _, _, _, _, _, _),
11+
(_, _, _, _, _, _, _, _, _, _),
12+
(_, _, _, _, _, _, _, _, _, _),
13+
14+
(_, _, _, _, _, _, _, _, _, _),
15+
(_, _, _, _, _, _, _, _, _, _),
16+
(_, _, _, _, _, _, _, _, _, _),
17+
(_, _, _, _, _, _, _, _, _, _),
18+
(_, _, _, _, _, _, _, _, _, _),
19+
(_, _, _, _, _, _, _, _, _, _),
20+
(_, _, _, _, _, _, _, _, _, _),
21+
(_, _, _, _, _, _, _, _, _, _),
22+
(_, _, _, _, _, _, _, _, _, _),
23+
(_, _, _, _, _, _, _, _, _, _),
24+
25+
(_, _, _, _, _, _, _, _, _, _),
26+
(_, _, _, _, _, _, _, _, _, _),
27+
(_, _, _, _, _, _, _, _, _, _),
28+
(_, _, _, _, _, _, _, _, _, _),
29+
(_, _, _, _, _, _, _, _, _, _),
30+
(_, _, _, _, _, _, _, _, _, _)) = 0
31+
32+
entrypoint not_too_many(
33+
(_, _, _, _, _, _, _, _, _, _),
34+
(_, _, _, _, _, _, _, _, _, _),
35+
(_, _, _, _, _, _, _, _, _, _),
36+
(_, _, _, _, _, _, _, _, _, _),
37+
(_, _, _, _, _, _, _, _, _, _),
38+
(_, _, _, _, _, _, _, _, _, _),
39+
(_, _, _, _, _, _, _, _, _, _),
40+
(_, _, _, _, _, _, _, _, _, _),
41+
(_, _, _, _, _, _, _, _, _, _),
42+
(_, _, _, _, _, _, _, _, _, _),
43+
44+
(_, _, _, _, _, _, _, _, _, _),
45+
(_, _, _, _, _, _, _, _, _, _),
46+
(_, _, _, _, _, _, _, _, _, _),
47+
(_, _, _, _, _, _, _, _, _, _),
48+
(_, _, _, _, _, _, _, _, _, _),
49+
(_, _, _, _, _, _, _, _, _, _),
50+
(_, _, _, _, _, _, _, _, _, _),
51+
(_, _, _, _, _, _, _, _, _, _),
52+
(_, _, _, _, _, _, _, _, _, _),
53+
(_, _, _, _, _, _, _, _, _, _),
54+
55+
(_, _, _, _, _, _, _, _, _, _),
56+
(_, _, _, _, _, _, _, _, _, _),
57+
(_, _, _, _, _, _, _, _, _, _),
58+
(_, _, _, _, _, _, _, _, _, _),
59+
(_, _, _, _, _, _, _, _, _, _),
60+
(_, _, _, _, _, _)) = 0

0 commit comments

Comments
 (0)