rbs 1.7.1 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/core/array.rbs +3 -3
- data/core/builtin.rbs +4 -0
- data/core/enumerable.rbs +3 -3
- data/docs/syntax.md +23 -20
- data/ext/rbs_extension/parser.c +96 -94
- data/ext/rbs_extension/ruby_objs.c +8 -6
- data/ext/rbs_extension/ruby_objs.h +2 -2
- data/lib/rbs/ast/declarations.rb +6 -2
- data/lib/rbs/cli.rb +1 -1
- data/lib/rbs/definition_builder.rb +29 -2
- data/lib/rbs/environment.rb +1 -0
- data/lib/rbs/environment_walker.rb +4 -1
- data/lib/rbs/errors.rb +12 -0
- data/lib/rbs/type_alias_regularity.rb +115 -0
- data/lib/rbs/types.rb +10 -22
- data/lib/rbs/validator.rb +40 -7
- data/lib/rbs/variance_calculator.rb +52 -24
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/writer.rb +1 -1
- data/lib/rbs.rb +1 -0
- data/schema/decls.json +13 -1
- data/schema/types.json +8 -2
- data/sig/declarations.rbs +9 -6
- data/sig/definition_builder.rbs +29 -0
- data/sig/environment_walker.rbs +26 -0
- data/sig/errors.rbs +10 -0
- data/sig/type_alias_regularity.rbs +92 -0
- data/sig/types.rbs +11 -8
- data/sig/validator.rbs +7 -0
- data/sig/variance_calculator.rbs +50 -0
- data/stdlib/date/0/date.rbs +2 -2
- data/stdlib/set/0/set.rbs +3 -3
- data/steep/Gemfile.lock +10 -10
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b12d92ea4eeeb5dbd6de6c5d58351b0306bdcd017d0f1e51a36599766bfded3
|
4
|
+
data.tar.gz: d60cfb836027441a5bb3f85fbebb0e2ab9bc03c49a21f00c3f10d4ab8dd1de65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ef926a62415189173d41204d1a16674a4a8331e3fdefafe00a4e52c9cbf0f3eb84281194a5b5c43027455334c13ea0ab14e1b3f0a6b8d5f5644cb80733a246b
|
7
|
+
data.tar.gz: ce07016eee6b4142a66a28d8c7ffc356b3d4fdd747027f2dd521b347efcb6ac791385e903a1e3b9f8d468ec66e13995e341516137ceba990db511982c6d0d206
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,29 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 1.8.0 (2021-12-02)
|
6
|
+
|
7
|
+
RBS 1.8.0 ships with a language feature enchancement, _generic type alias_.
|
8
|
+
You can define a type alias with type parameters now.
|
9
|
+
|
10
|
+
```rbs
|
11
|
+
type list[T] = [T, list[T]] | nil # Defines a list of type T
|
12
|
+
|
13
|
+
type int_list = list[Integer] # List of Integer
|
14
|
+
type string_list = list[String] # List of String
|
15
|
+
```
|
16
|
+
|
17
|
+
You can find the detail in the [PR](https://github.com/ruby/rbs/pull/823).
|
18
|
+
|
19
|
+
### Signature updates
|
20
|
+
|
21
|
+
* `Date#+`, `Date#-` ([\#830](https://github.com/ruby/rbs/pull/830))
|
22
|
+
* `#include?`, `#member?`, `#delete`, `#count` ([\#835](https://github.com/ruby/rbs/pull/835))
|
23
|
+
|
24
|
+
### Language updates
|
25
|
+
|
26
|
+
* Generic type alias ([\#823](https://github.com/ruby/rbs/pull/823))
|
27
|
+
|
5
28
|
## 1.7.1 (2021-11-18)
|
6
29
|
|
7
30
|
### Signature updates
|
data/core/array.rbs
CHANGED
@@ -699,7 +699,7 @@ class Array[unchecked out Elem] < Object
|
|
699
699
|
# ary.count {|x| x%2 == 0} #=> 3
|
700
700
|
#
|
701
701
|
def count: () -> ::Integer
|
702
|
-
| (
|
702
|
+
| (Elem obj) -> ::Integer
|
703
703
|
| () { (Elem) -> boolish } -> ::Integer
|
704
704
|
|
705
705
|
# Calls the given block for each element `n` times or forever if `nil` is given.
|
@@ -733,7 +733,7 @@ class Array[unchecked out Elem] < Object
|
|
733
733
|
# a.delete("z") #=> nil
|
734
734
|
# a.delete("z") {"not found"} #=> "not found"
|
735
735
|
#
|
736
|
-
def delete: (
|
736
|
+
def delete: (Elem obj) -> Elem?
|
737
737
|
| [S, T] (S obj) { (S) -> T } -> (Elem | T)
|
738
738
|
|
739
739
|
# Deletes the element at the specified `index`, returning that element, or `nil`
|
@@ -1029,7 +1029,7 @@ class Array[unchecked out Elem] < Object
|
|
1029
1029
|
# a.include?("b") #=> true
|
1030
1030
|
# a.include?("z") #=> false
|
1031
1031
|
#
|
1032
|
-
def include?: (
|
1032
|
+
def include?: (Elem object) -> bool
|
1033
1033
|
|
1034
1034
|
# Returns the *index* of the first object in `ary` such that the object is `==`
|
1035
1035
|
# to `obj`.
|
data/core/builtin.rbs
CHANGED
data/core/enumerable.rbs
CHANGED
@@ -63,7 +63,7 @@ module Enumerable[unchecked out Elem]: _Each[Elem]
|
|
63
63
|
# ary.count{ |x| x%2==0 } #=> 3
|
64
64
|
# ```
|
65
65
|
def count: () -> Integer
|
66
|
-
| (
|
66
|
+
| (Elem) -> Integer
|
67
67
|
| () { (Elem) -> boolish } -> Integer
|
68
68
|
|
69
69
|
def cycle: (?Integer n) { (Elem arg0) -> untyped } -> NilClass
|
@@ -130,7 +130,7 @@ module Enumerable[unchecked out Elem]: _Each[Elem]
|
|
130
130
|
def group_by: [U] () { (Elem arg0) -> U } -> ::Hash[U, ::Array[Elem]]
|
131
131
|
| () -> ::Enumerator[Elem, ::Array[Elem]]
|
132
132
|
|
133
|
-
def `include?`: (
|
133
|
+
def `include?`: (Elem arg0) -> bool
|
134
134
|
|
135
135
|
def inject: (untyped init, Symbol method) -> untyped
|
136
136
|
| (Symbol method) -> untyped
|
@@ -341,7 +341,7 @@ module Enumerable[unchecked out Elem]: _Each[Elem]
|
|
341
341
|
def map: [U] () { (Elem arg0) -> U } -> ::Array[U]
|
342
342
|
| () -> ::Enumerator[Elem, ::Array[untyped]]
|
343
343
|
|
344
|
-
def member?: (
|
344
|
+
def member?: (Elem arg0) -> bool
|
345
345
|
|
346
346
|
alias reduce inject
|
347
347
|
|
data/docs/syntax.md
CHANGED
@@ -5,14 +5,14 @@
|
|
5
5
|
```markdown
|
6
6
|
_type_ ::= _class-name_ _type-arguments_ (Class instance type)
|
7
7
|
| _interface-name_ _type-arguments_ (Interface type)
|
8
|
+
| _alias-name_ _type-arguments_ (Alias type)
|
8
9
|
| `singleton(` _class-name_ `)` (Class singleton type)
|
9
|
-
| _alias-name_ (Alias type)
|
10
10
|
| _literal_ (Literal type)
|
11
11
|
| _type_ `|` _type_ (Union type)
|
12
12
|
| _type_ `&` _type_ (Intersection type)
|
13
13
|
| _type_ `?` (Optional type)
|
14
|
-
| `{` _record-name_ `:` _type_ `,` etc. `}`
|
15
|
-
| `[]` | `[` _type_ `,` etc. `]`
|
14
|
+
| `{` _record-name_ `:` _type_ `,` etc. `}` (Record type)
|
15
|
+
| `[]` | `[` _type_ `,` etc. `]` (Tuples)
|
16
16
|
| _type-variable_ (Type variables)
|
17
17
|
| `^(` _parameters_ `) ->` _type_ (Proc type)
|
18
18
|
| `self`
|
@@ -35,8 +35,8 @@ _namespace_ ::= (Empty namespace)
|
|
35
35
|
| `::` (Root)
|
36
36
|
| _namespace_ /[A-Z]\w*/ `::` (Namespace)
|
37
37
|
|
38
|
-
_type-arguments_ ::= (No
|
39
|
-
| `[` _type_ `,` etc. `]`
|
38
|
+
_type-arguments_ ::= (No type arguments)
|
39
|
+
| `[` _type_ `,` etc. `]` (Type arguments)
|
40
40
|
|
41
41
|
_literal_ ::= _string-literal_
|
42
42
|
| _symbol-literal_
|
@@ -64,25 +64,25 @@ _ToS # _ToS interface
|
|
64
64
|
::MyApp::_Each[String] # Interface name with namespace and type application
|
65
65
|
```
|
66
66
|
|
67
|
-
### Class singleton type
|
68
|
-
|
69
|
-
Class singleton type denotes _the type of a singleton object of a class_.
|
70
|
-
|
71
|
-
```
|
72
|
-
singleton(String)
|
73
|
-
singleton(::Hash) # Class singleton type cannot be parametrized.
|
74
|
-
```
|
75
|
-
|
76
67
|
### Alias type
|
77
68
|
|
78
69
|
Alias type denotes an alias declared with _alias declaration_.
|
79
70
|
|
80
71
|
The name of type aliases starts with lowercase `[a-z]`.
|
81
72
|
|
82
|
-
|
83
73
|
```
|
84
74
|
name
|
85
75
|
::JSON::t # Alias name with namespace
|
76
|
+
list[Integer] # Type alias can be generic
|
77
|
+
```
|
78
|
+
|
79
|
+
### Class singleton type
|
80
|
+
|
81
|
+
Class singleton type denotes _the type of a singleton object of a class_.
|
82
|
+
|
83
|
+
```
|
84
|
+
singleton(String)
|
85
|
+
singleton(::Hash) # Class singleton type cannot be parametrized.
|
86
86
|
```
|
87
87
|
|
88
88
|
### Literal type
|
@@ -155,7 +155,7 @@ Elem
|
|
155
155
|
```
|
156
156
|
|
157
157
|
Type variables cannot be distinguished from _class instance types_.
|
158
|
-
They are scoped in _class/module/interface declaration_ or _generic method types_.
|
158
|
+
They are scoped in _class/module/interface/alias declaration_ or _generic method types_.
|
159
159
|
|
160
160
|
```
|
161
161
|
class Ref[T] # Object is scoped in the class declaration.
|
@@ -414,7 +414,6 @@ These work only as _statements_, not per-method specifier.
|
|
414
414
|
_decl_ ::= _class-decl_ # Class declaration
|
415
415
|
| _module-decl_ # Module declaration
|
416
416
|
| _interface-decl_ # Interface declaration
|
417
|
-
| _extension-decl_ # Extension declaration
|
418
417
|
| _type-alias-decl_ # Type alias declaration
|
419
418
|
| _const-decl_ # Constant declaration
|
420
419
|
| _global-decl_ # Global declaration
|
@@ -434,9 +433,7 @@ _interface-members_ ::= _method-member_ # Method
|
|
434
433
|
| _include-member_ # Mixin (include)
|
435
434
|
| _alias-member_ # Alias
|
436
435
|
|
437
|
-
|
438
|
-
|
439
|
-
_type-alias-decl_ ::= `type` _alias-name_ `=` _type_
|
436
|
+
_type-alias-decl_ ::= `type` _alias-name_ _module-type-parameters_ `=` _type_
|
440
437
|
|
441
438
|
_const-decl_ ::= _const-name_ `:` _type_
|
442
439
|
|
@@ -536,6 +533,12 @@ type subject = Attendee | Speaker
|
|
536
533
|
type JSON::t = Integer | TrueClass | FalseClass | String | Hash[Symbol, t] | Array[t]
|
537
534
|
```
|
538
535
|
|
536
|
+
Type alias can be generic like class, module, and interface.
|
537
|
+
|
538
|
+
```
|
539
|
+
type list[out T] = [T, list[T]] | nil
|
540
|
+
```
|
541
|
+
|
539
542
|
### Constant type declaration
|
540
543
|
|
541
544
|
You can declare a constant.
|
data/ext/rbs_extension/parser.c
CHANGED
@@ -815,6 +815,8 @@ static VALUE parse_simple(parserstate *state) {
|
|
815
815
|
}
|
816
816
|
case tULIDENT:
|
817
817
|
// fallthrough
|
818
|
+
case tLIDENT:
|
819
|
+
// fallthrough
|
818
820
|
case pCOLON2: {
|
819
821
|
range name_range;
|
820
822
|
range args_range;
|
@@ -857,19 +859,11 @@ static VALUE parse_simple(parserstate *state) {
|
|
857
859
|
} else if (kind == INTERFACE_NAME) {
|
858
860
|
return rbs_interface(typename, types, location);
|
859
861
|
} else if (kind == ALIAS_NAME) {
|
860
|
-
return rbs_alias(typename, location);
|
862
|
+
return rbs_alias(typename, types, location);
|
861
863
|
} else {
|
862
864
|
return Qnil;
|
863
865
|
}
|
864
866
|
}
|
865
|
-
case tLIDENT: {
|
866
|
-
VALUE location = rbs_location_current_token(state);
|
867
|
-
rbs_loc *loc = rbs_check_location(location);
|
868
|
-
rbs_loc_add_required_child(loc, rb_intern("name"), state->current_token.range);
|
869
|
-
rbs_loc_add_optional_child(loc, rb_intern("args"), NULL_RANGE);
|
870
|
-
VALUE typename = parse_type_name(state, ALIAS_NAME, NULL);
|
871
|
-
return rbs_alias(typename, location);
|
872
|
-
}
|
873
867
|
case kSINGLETON: {
|
874
868
|
range name_range;
|
875
869
|
range type_range;
|
@@ -1093,12 +1087,98 @@ VALUE parse_const_decl(parserstate *state) {
|
|
1093
1087
|
return rbs_ast_decl_constant(typename, type, location, comment);
|
1094
1088
|
}
|
1095
1089
|
|
1090
|
+
/*
|
1091
|
+
module_type_params ::= {} `[` module_type_param `,` ... <`]`>
|
1092
|
+
| {<>}
|
1093
|
+
|
1094
|
+
module_type_param ::= kUNCHECKED? (kIN|kOUT|) tUIDENT
|
1095
|
+
*/
|
1096
|
+
VALUE parse_module_type_params(parserstate *state, range *rg) {
|
1097
|
+
VALUE params = rbs_ast_decl_module_type_params();
|
1098
|
+
|
1099
|
+
if (state->next_token.type == pLBRACKET) {
|
1100
|
+
parser_advance(state);
|
1101
|
+
|
1102
|
+
rg->start = state->current_token.range.start;
|
1103
|
+
|
1104
|
+
while (true) {
|
1105
|
+
VALUE name;
|
1106
|
+
VALUE unchecked = Qfalse;
|
1107
|
+
VALUE variance = ID2SYM(rb_intern("invariant"));
|
1108
|
+
|
1109
|
+
range param_range = NULL_RANGE;
|
1110
|
+
range name_range;
|
1111
|
+
range variance_range = NULL_RANGE;
|
1112
|
+
range unchecked_range = NULL_RANGE;
|
1113
|
+
|
1114
|
+
param_range.start = state->next_token.range.start;
|
1115
|
+
|
1116
|
+
if (state->next_token.type == kUNCHECKED) {
|
1117
|
+
unchecked = Qtrue;
|
1118
|
+
parser_advance(state);
|
1119
|
+
unchecked_range = state->current_token.range;
|
1120
|
+
}
|
1121
|
+
|
1122
|
+
if (state->next_token.type == kIN || state->next_token.type == kOUT) {
|
1123
|
+
switch (state->next_token.type) {
|
1124
|
+
case kIN:
|
1125
|
+
variance = ID2SYM(rb_intern("contravariant"));
|
1126
|
+
break;
|
1127
|
+
case kOUT:
|
1128
|
+
variance = ID2SYM(rb_intern("covariant"));
|
1129
|
+
break;
|
1130
|
+
default:
|
1131
|
+
rbs_abort();
|
1132
|
+
}
|
1133
|
+
|
1134
|
+
parser_advance(state);
|
1135
|
+
variance_range = state->current_token.range;
|
1136
|
+
}
|
1137
|
+
|
1138
|
+
parser_advance_assert(state, tUIDENT);
|
1139
|
+
name_range = state->current_token.range;
|
1140
|
+
param_range.end = state->current_token.range.end;
|
1141
|
+
|
1142
|
+
ID id = INTERN_TOKEN(state, state->current_token);
|
1143
|
+
name = ID2SYM(id);
|
1144
|
+
|
1145
|
+
parser_insert_typevar(state, id);
|
1146
|
+
|
1147
|
+
VALUE location = rbs_new_location(state->buffer, param_range);
|
1148
|
+
rbs_loc *loc = rbs_check_location(location);
|
1149
|
+
rbs_loc_add_required_child(loc, rb_intern("name"), name_range);
|
1150
|
+
rbs_loc_add_optional_child(loc, rb_intern("variance"), variance_range);
|
1151
|
+
rbs_loc_add_optional_child(loc, rb_intern("unchecked"), unchecked_range);
|
1152
|
+
|
1153
|
+
VALUE param = rbs_ast_decl_module_type_params_param(name, variance, unchecked, location);
|
1154
|
+
rb_funcall(params, rb_intern("add"), 1, param);
|
1155
|
+
|
1156
|
+
if (state->next_token.type == pCOMMA) {
|
1157
|
+
parser_advance(state);
|
1158
|
+
}
|
1159
|
+
|
1160
|
+
if (state->next_token.type == pRBRACKET) {
|
1161
|
+
break;
|
1162
|
+
}
|
1163
|
+
}
|
1164
|
+
|
1165
|
+
parser_advance_assert(state, pRBRACKET);
|
1166
|
+
rg->end = state->current_token.range.end;
|
1167
|
+
} else {
|
1168
|
+
*rg = NULL_RANGE;
|
1169
|
+
}
|
1170
|
+
|
1171
|
+
return params;
|
1172
|
+
}
|
1173
|
+
|
1096
1174
|
/*
|
1097
1175
|
type_decl ::= {kTYPE} alias_name `=` <type>
|
1098
1176
|
*/
|
1099
1177
|
VALUE parse_type_decl(parserstate *state, position comment_pos, VALUE annotations) {
|
1100
1178
|
range decl_range;
|
1101
|
-
range keyword_range, name_range, eq_range;
|
1179
|
+
range keyword_range, name_range, params_range, eq_range;
|
1180
|
+
|
1181
|
+
parser_push_typevar_table(state, true);
|
1102
1182
|
|
1103
1183
|
decl_range.start = state->current_token.range.start;
|
1104
1184
|
comment_pos = nonnull_pos_or(comment_pos, decl_range.start);
|
@@ -1108,6 +1188,8 @@ VALUE parse_type_decl(parserstate *state, position comment_pos, VALUE annotation
|
|
1108
1188
|
parser_advance(state);
|
1109
1189
|
VALUE typename = parse_type_name(state, ALIAS_NAME, &name_range);
|
1110
1190
|
|
1191
|
+
VALUE type_params = parse_module_type_params(state, ¶ms_range);
|
1192
|
+
|
1111
1193
|
parser_advance_assert(state, pEQ);
|
1112
1194
|
eq_range = state->current_token.range;
|
1113
1195
|
|
@@ -1118,10 +1200,14 @@ VALUE parse_type_decl(parserstate *state, position comment_pos, VALUE annotation
|
|
1118
1200
|
rbs_loc *loc = rbs_check_location(location);
|
1119
1201
|
rbs_loc_add_required_child(loc, rb_intern("keyword"), keyword_range);
|
1120
1202
|
rbs_loc_add_required_child(loc, rb_intern("name"), name_range);
|
1203
|
+
rbs_loc_add_optional_child(loc, rb_intern("type_params"), params_range);
|
1121
1204
|
rbs_loc_add_required_child(loc, rb_intern("eq"), eq_range);
|
1122
1205
|
|
1206
|
+
parser_pop_typevar_table(state);
|
1207
|
+
|
1123
1208
|
return rbs_ast_decl_alias(
|
1124
1209
|
typename,
|
1210
|
+
type_params,
|
1125
1211
|
type,
|
1126
1212
|
annotations,
|
1127
1213
|
location,
|
@@ -1184,90 +1270,6 @@ VALUE parse_annotation(parserstate *state) {
|
|
1184
1270
|
return rbs_ast_annotation(string, location);
|
1185
1271
|
}
|
1186
1272
|
|
1187
|
-
/*
|
1188
|
-
module_type_params ::= {} `[` module_type_param `,` ... <`]`>
|
1189
|
-
| {<>}
|
1190
|
-
|
1191
|
-
module_type_param ::= kUNCHECKED? (kIN|kOUT|) tUIDENT
|
1192
|
-
*/
|
1193
|
-
VALUE parse_module_type_params(parserstate *state, range *rg) {
|
1194
|
-
VALUE params = rbs_ast_decl_module_type_params();
|
1195
|
-
|
1196
|
-
if (state->next_token.type == pLBRACKET) {
|
1197
|
-
parser_advance(state);
|
1198
|
-
|
1199
|
-
rg->start = state->current_token.range.start;
|
1200
|
-
|
1201
|
-
while (true) {
|
1202
|
-
VALUE name;
|
1203
|
-
VALUE unchecked = Qfalse;
|
1204
|
-
VALUE variance = ID2SYM(rb_intern("invariant"));
|
1205
|
-
|
1206
|
-
range param_range = NULL_RANGE;
|
1207
|
-
range name_range;
|
1208
|
-
range variance_range = NULL_RANGE;
|
1209
|
-
range unchecked_range = NULL_RANGE;
|
1210
|
-
|
1211
|
-
param_range.start = state->next_token.range.start;
|
1212
|
-
|
1213
|
-
if (state->next_token.type == kUNCHECKED) {
|
1214
|
-
unchecked = Qtrue;
|
1215
|
-
parser_advance(state);
|
1216
|
-
unchecked_range = state->current_token.range;
|
1217
|
-
}
|
1218
|
-
|
1219
|
-
if (state->next_token.type == kIN || state->next_token.type == kOUT) {
|
1220
|
-
switch (state->next_token.type) {
|
1221
|
-
case kIN:
|
1222
|
-
variance = ID2SYM(rb_intern("contravariant"));
|
1223
|
-
break;
|
1224
|
-
case kOUT:
|
1225
|
-
variance = ID2SYM(rb_intern("covariant"));
|
1226
|
-
break;
|
1227
|
-
default:
|
1228
|
-
rbs_abort();
|
1229
|
-
}
|
1230
|
-
|
1231
|
-
parser_advance(state);
|
1232
|
-
variance_range = state->current_token.range;
|
1233
|
-
}
|
1234
|
-
|
1235
|
-
parser_advance_assert(state, tUIDENT);
|
1236
|
-
name_range = state->current_token.range;
|
1237
|
-
param_range.end = state->current_token.range.end;
|
1238
|
-
|
1239
|
-
ID id = INTERN_TOKEN(state, state->current_token);
|
1240
|
-
name = ID2SYM(id);
|
1241
|
-
|
1242
|
-
parser_insert_typevar(state, id);
|
1243
|
-
|
1244
|
-
VALUE location = rbs_new_location(state->buffer, param_range);
|
1245
|
-
rbs_loc *loc = rbs_check_location(location);
|
1246
|
-
rbs_loc_add_required_child(loc, rb_intern("name"), name_range);
|
1247
|
-
rbs_loc_add_optional_child(loc, rb_intern("variance"), variance_range);
|
1248
|
-
rbs_loc_add_optional_child(loc, rb_intern("unchecked"), unchecked_range);
|
1249
|
-
|
1250
|
-
VALUE param = rbs_ast_decl_module_type_params_param(name, variance, unchecked, location);
|
1251
|
-
rb_funcall(params, rb_intern("add"), 1, param);
|
1252
|
-
|
1253
|
-
if (state->next_token.type == pCOMMA) {
|
1254
|
-
parser_advance(state);
|
1255
|
-
}
|
1256
|
-
|
1257
|
-
if (state->next_token.type == pRBRACKET) {
|
1258
|
-
break;
|
1259
|
-
}
|
1260
|
-
}
|
1261
|
-
|
1262
|
-
parser_advance_assert(state, pRBRACKET);
|
1263
|
-
rg->end = state->current_token.range.end;
|
1264
|
-
} else {
|
1265
|
-
*rg = NULL_RANGE;
|
1266
|
-
}
|
1267
|
-
|
1268
|
-
return params;
|
1269
|
-
}
|
1270
|
-
|
1271
1273
|
/*
|
1272
1274
|
annotations ::= {} annotation ... <annotation>
|
1273
1275
|
| {<>}
|
@@ -70,15 +70,16 @@ VALUE rbs_class_singleton(VALUE typename, VALUE location) {
|
|
70
70
|
);
|
71
71
|
}
|
72
72
|
|
73
|
-
VALUE rbs_alias(VALUE typename, VALUE location) {
|
74
|
-
VALUE
|
75
|
-
rb_hash_aset(
|
76
|
-
rb_hash_aset(
|
73
|
+
VALUE rbs_alias(VALUE typename, VALUE args, VALUE location) {
|
74
|
+
VALUE kwargs = rb_hash_new();
|
75
|
+
rb_hash_aset(kwargs, ID2SYM(rb_intern("name")), typename);
|
76
|
+
rb_hash_aset(kwargs, ID2SYM(rb_intern("args")), args);
|
77
|
+
rb_hash_aset(kwargs, ID2SYM(rb_intern("location")), location);
|
77
78
|
|
78
79
|
return CLASS_NEW_INSTANCE(
|
79
80
|
RBS_Types_Alias,
|
80
81
|
1,
|
81
|
-
&
|
82
|
+
&kwargs
|
82
83
|
);
|
83
84
|
}
|
84
85
|
|
@@ -339,9 +340,10 @@ VALUE rbs_ast_decl_global(VALUE name, VALUE type, VALUE location, VALUE comment)
|
|
339
340
|
);
|
340
341
|
}
|
341
342
|
|
342
|
-
VALUE rbs_ast_decl_alias(VALUE name, VALUE type, VALUE annotations, VALUE location, VALUE comment) {
|
343
|
+
VALUE rbs_ast_decl_alias(VALUE name, VALUE type_params, VALUE type, VALUE annotations, VALUE location, VALUE comment) {
|
343
344
|
VALUE args = rb_hash_new();
|
344
345
|
rb_hash_aset(args, ID2SYM(rb_intern("name")), name);
|
346
|
+
rb_hash_aset(args, ID2SYM(rb_intern("type_params")), type_params);
|
345
347
|
rb_hash_aset(args, ID2SYM(rb_intern("type")), type);
|
346
348
|
rb_hash_aset(args, ID2SYM(rb_intern("annotations")), annotations);
|
347
349
|
rb_hash_aset(args, ID2SYM(rb_intern("location")), location);
|
@@ -3,10 +3,10 @@
|
|
3
3
|
|
4
4
|
#include "ruby.h"
|
5
5
|
|
6
|
-
VALUE rbs_alias(VALUE typename, VALUE location);
|
6
|
+
VALUE rbs_alias(VALUE typename, VALUE args, VALUE location);
|
7
7
|
VALUE rbs_ast_annotation(VALUE string, VALUE location);
|
8
8
|
VALUE rbs_ast_comment(VALUE string, VALUE location);
|
9
|
-
VALUE rbs_ast_decl_alias(VALUE name, VALUE type, VALUE annotations, VALUE location, VALUE comment);
|
9
|
+
VALUE rbs_ast_decl_alias(VALUE name, VALUE type_params, VALUE type, VALUE annotations, VALUE location, VALUE comment);
|
10
10
|
VALUE rbs_ast_decl_class_super(VALUE name, VALUE args, VALUE location);
|
11
11
|
VALUE rbs_ast_decl_class(VALUE name, VALUE type_params, VALUE super_class, VALUE members, VALUE annotations, VALUE location, VALUE comment);
|
12
12
|
VALUE rbs_ast_decl_constant(VALUE name, VALUE type, VALUE location, VALUE comment);
|
data/lib/rbs/ast/declarations.rb
CHANGED
@@ -362,13 +362,15 @@ module RBS
|
|
362
362
|
|
363
363
|
class Alias < Base
|
364
364
|
attr_reader :name
|
365
|
+
attr_reader :type_params
|
365
366
|
attr_reader :type
|
366
367
|
attr_reader :annotations
|
367
368
|
attr_reader :location
|
368
369
|
attr_reader :comment
|
369
370
|
|
370
|
-
def initialize(name:, type:, annotations:, location:, comment:)
|
371
|
+
def initialize(name:, type_params:, type:, annotations:, location:, comment:)
|
371
372
|
@name = name
|
373
|
+
@type_params = type_params
|
372
374
|
@type = type
|
373
375
|
@annotations = annotations
|
374
376
|
@location = location
|
@@ -378,19 +380,21 @@ module RBS
|
|
378
380
|
def ==(other)
|
379
381
|
other.is_a?(Alias) &&
|
380
382
|
other.name == name &&
|
383
|
+
other.type_params == type_params &&
|
381
384
|
other.type == type
|
382
385
|
end
|
383
386
|
|
384
387
|
alias eql? ==
|
385
388
|
|
386
389
|
def hash
|
387
|
-
self.class.hash ^ name.hash ^ type.hash
|
390
|
+
self.class.hash ^ name.hash ^ type_params.hash ^ type.hash
|
388
391
|
end
|
389
392
|
|
390
393
|
def to_json(state = _ = nil)
|
391
394
|
{
|
392
395
|
declaration: :alias,
|
393
396
|
name: name,
|
397
|
+
type_params: type_params,
|
394
398
|
type: type,
|
395
399
|
annotations: annotations,
|
396
400
|
location: location,
|
data/lib/rbs/cli.rb
CHANGED
@@ -460,7 +460,7 @@ EOU
|
|
460
460
|
|
461
461
|
env.alias_decls.each do |name, decl|
|
462
462
|
stdout.puts "Validating alias: `#{name}`..."
|
463
|
-
builder.
|
463
|
+
builder.expand_alias1(name).tap do |type|
|
464
464
|
validator.validate_type type, context: [Namespace.root]
|
465
465
|
end
|
466
466
|
validator.validate_type_alias(entry: decl)
|
@@ -781,9 +781,36 @@ module RBS
|
|
781
781
|
end
|
782
782
|
|
783
783
|
def expand_alias(type_name)
|
784
|
-
|
784
|
+
expand_alias2(type_name, [])
|
785
|
+
end
|
786
|
+
|
787
|
+
def expand_alias1(type_name)
|
788
|
+
entry = env.alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
|
789
|
+
as = entry.decl.type_params.each.map { Types::Bases::Any.new(location: nil) }
|
790
|
+
expand_alias2(type_name, as)
|
791
|
+
end
|
792
|
+
|
793
|
+
def expand_alias2(type_name, args)
|
794
|
+
entry = env.alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
|
795
|
+
|
785
796
|
ensure_namespace!(type_name.namespace, location: entry.decl.location)
|
786
|
-
entry.decl.
|
797
|
+
params = entry.decl.type_params.each.map(&:name)
|
798
|
+
|
799
|
+
unless params.size == args.size
|
800
|
+
as = "[#{args.join(", ")}]" unless args.empty?
|
801
|
+
ps = "[#{params.join(", ")}]" unless params.empty?
|
802
|
+
|
803
|
+
raise "Invalid type application: type = #{type_name}#{as}, decl = #{type_name}#{ps}"
|
804
|
+
end
|
805
|
+
|
806
|
+
type = entry.decl.type
|
807
|
+
|
808
|
+
unless params.empty?
|
809
|
+
subst = Substitution.build(params, args)
|
810
|
+
type = type.sub(subst)
|
811
|
+
end
|
812
|
+
|
813
|
+
type
|
787
814
|
end
|
788
815
|
|
789
816
|
def update(env:, except:, ancestor_builder:)
|
data/lib/rbs/environment.rb
CHANGED
@@ -319,6 +319,7 @@ module RBS
|
|
319
319
|
when AST::Declarations::Alias
|
320
320
|
AST::Declarations::Alias.new(
|
321
321
|
name: decl.name.with_prefix(prefix),
|
322
|
+
type_params: decl.type_params,
|
322
323
|
type: absolute_type(resolver, decl.type, context: context),
|
323
324
|
location: decl.location,
|
324
325
|
annotations: decl.annotations,
|
@@ -57,7 +57,7 @@ module RBS
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
when name.alias?
|
60
|
-
each_type_node builder.
|
60
|
+
each_type_node builder.expand_alias1(name), &block
|
61
61
|
else
|
62
62
|
raise "Unexpected TypeNameNode with type_name=#{name}"
|
63
63
|
end
|
@@ -126,6 +126,9 @@ module RBS
|
|
126
126
|
end
|
127
127
|
when RBS::Types::Alias
|
128
128
|
yield TypeNameNode.new(type_name: type.name)
|
129
|
+
type.args.each do |ty|
|
130
|
+
each_type_node(ty, &block)
|
131
|
+
end
|
129
132
|
when RBS::Types::Union, RBS::Types::Intersection, RBS::Types::Tuple
|
130
133
|
type.types.each do |ty|
|
131
134
|
each_type_node ty, &block
|
data/lib/rbs/errors.rb
CHANGED
@@ -431,4 +431,16 @@ module RBS
|
|
431
431
|
@alias_names.map(&:name).join(', ')
|
432
432
|
end
|
433
433
|
end
|
434
|
+
|
435
|
+
class NonregularTypeAliasError < LoadingError
|
436
|
+
attr_reader :diagnostic
|
437
|
+
attr_reader :location
|
438
|
+
|
439
|
+
def initialize(diagnostic:, location:)
|
440
|
+
@diagnostic = diagnostic
|
441
|
+
@location = location
|
442
|
+
|
443
|
+
super "#{Location.to_string location}: Nonregular generic type alias is prohibited: #{diagnostic.type_name}, #{diagnostic.nonregular_type}"
|
444
|
+
end
|
445
|
+
end
|
434
446
|
end
|