rbs 1.7.0.beta.5 → 1.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/CHANGELOG.md +64 -3
  4. data/Steepfile +0 -1
  5. data/core/array.rbs +3 -3
  6. data/core/builtin.rbs +4 -0
  7. data/core/enumerable.rbs +3 -3
  8. data/core/env.rbs +881 -0
  9. data/core/false_class.rbs +2 -0
  10. data/core/nil_class.rbs +2 -0
  11. data/core/symbol.rbs +2 -0
  12. data/core/thread.rbs +1 -1
  13. data/core/true_class.rbs +2 -0
  14. data/docs/syntax.md +23 -20
  15. data/ext/rbs_extension/parser.c +97 -95
  16. data/ext/rbs_extension/ruby_objs.c +8 -6
  17. data/ext/rbs_extension/ruby_objs.h +2 -2
  18. data/lib/rbs/ast/declarations.rb +6 -2
  19. data/lib/rbs/cli.rb +1 -1
  20. data/lib/rbs/collection/sources/git.rb +9 -7
  21. data/lib/rbs/definition_builder.rb +58 -2
  22. data/lib/rbs/environment.rb +1 -0
  23. data/lib/rbs/environment_walker.rb +4 -1
  24. data/lib/rbs/errors.rb +12 -0
  25. data/lib/rbs/test/setup.rb +1 -0
  26. data/lib/rbs/type_alias_regularity.rb +115 -0
  27. data/lib/rbs/types.rb +11 -23
  28. data/lib/rbs/validator.rb +44 -15
  29. data/lib/rbs/variance_calculator.rb +52 -24
  30. data/lib/rbs/version.rb +1 -1
  31. data/lib/rbs/writer.rb +1 -1
  32. data/lib/rbs.rb +1 -0
  33. data/schema/decls.json +13 -1
  34. data/schema/types.json +8 -2
  35. data/sig/collection/collections.rbs +4 -2
  36. data/sig/declarations.rbs +9 -6
  37. data/sig/definition_builder.rbs +36 -0
  38. data/sig/environment_walker.rbs +26 -0
  39. data/sig/errors.rbs +10 -0
  40. data/sig/type_alias_regularity.rbs +92 -0
  41. data/sig/types.rbs +11 -8
  42. data/sig/validator.rbs +7 -0
  43. data/sig/variance_calculator.rbs +50 -0
  44. data/stdlib/bigdecimal/0/big_decimal.rbs +44 -0
  45. data/stdlib/csv/0/csv.rbs +49 -3
  46. data/stdlib/date/0/date.rbs +2 -2
  47. data/stdlib/set/0/set.rbs +3 -3
  48. data/steep/Gemfile.lock +10 -10
  49. metadata +7 -6
  50. data/lib/rbs/parser.y +0 -1805
  51. data/lib/ruby/signature.rb +0 -7
data/core/false_class.rbs CHANGED
@@ -37,4 +37,6 @@ class FalseClass
37
37
  def |: (nil) -> false
38
38
  | (false) -> false
39
39
  | (untyped obj) -> true
40
+
41
+ def clone: (?freeze: true?) -> self
40
42
  end
data/core/nil_class.rbs CHANGED
@@ -79,4 +79,6 @@ class NilClass
79
79
  def |: (nil) -> false
80
80
  | (false) -> false
81
81
  | (untyped obj) -> bool
82
+
83
+ def clone: (?freeze: true?) -> self
82
84
  end
data/core/symbol.rbs CHANGED
@@ -226,4 +226,6 @@ class Symbol
226
226
  | (:ascii | :lithuanian | :turkic) -> Symbol
227
227
  | (:lithuanian, :turkic) -> Symbol
228
228
  | (:turkic, :lithuanian) -> Symbol
229
+
230
+ def clone: (?freeze: true?) -> self
229
231
  end
data/core/thread.rbs CHANGED
@@ -554,7 +554,7 @@ class Thread < Object
554
554
  # b = Thread.new { raise 'something went wrong' }
555
555
  # b.value #=> RuntimeError: something went wrong
556
556
  # ```
557
- def value: () -> Object
557
+ def value: () -> untyped
558
558
 
559
559
  # Marks a given thread as eligible for scheduling, however it may still
560
560
  # remain blocked on I/O.
data/core/true_class.rbs CHANGED
@@ -43,4 +43,6 @@ class TrueClass
43
43
  # or
44
44
  #
45
45
  def |: (untyped obj) -> true
46
+
47
+ def clone: (?freeze: true?) -> self
46
48
  end
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. `}` (Record type)
15
- | `[]` | `[` _type_ `,` etc. `]` (Tuples)
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 application)
39
- | `[` _type_ `,` etc. `]` (Type application)
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
- _extension-decl_ ::= `extension` _class-name_ _type-parameters_ `(` _extension-name_ `)` _members_ `end`
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.
@@ -273,7 +273,7 @@ static VALUE parse_function_param(parserstate *state) {
273
273
  param_range.start = type_range.start;
274
274
  param_range.end = name_range.end;
275
275
 
276
- VALUE name = ID2SYM(INTERN_TOKEN(state, state->current_token));
276
+ VALUE name = rb_to_symbol(rbs_unquote_string(state, state->current_token.range, 0));
277
277
  VALUE location = rbs_new_location(state->buffer, param_range);
278
278
  rbs_loc *loc = rbs_check_location(location);
279
279
  rbs_loc_add_optional_child(loc, rb_intern("name"), name_range);
@@ -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, &params_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 args = rb_hash_new();
75
- rb_hash_aset(args, ID2SYM(rb_intern("name")), typename);
76
- rb_hash_aset(args, ID2SYM(rb_intern("location")), location);
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
- &args
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);
@@ -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.expand_alias(name).tap do |type|
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)
@@ -104,9 +104,9 @@ module RBS
104
104
  else
105
105
  begin
106
106
  # git v2.27.0 or greater
107
- git 'clone', '--filter=blob:none', remote, git_dir.to_s
107
+ git 'clone', '--filter=blob:none', remote, git_dir.to_s, chdir: nil
108
108
  rescue CommandError
109
- git 'clone', remote, git_dir.to_s
109
+ git 'clone', remote, git_dir.to_s, chdir: nil
110
110
  end
111
111
  end
112
112
 
@@ -131,7 +131,8 @@ module RBS
131
131
  private def git_dir
132
132
  @git_dir ||= (
133
133
  base = Pathname(ENV['XDG_CACHE_HOME'] || File.expand_path("~/.cache"))
134
- dir = base.join('rbs', Digest::SHA256.hexdigest(remote))
134
+ cache_key = remote.start_with?('.') ? "#{remote}\0#{Dir.pwd}" : remote
135
+ dir = base.join('rbs', Digest::SHA256.hexdigest(cache_key))
135
136
  dir.mkpath
136
137
  dir
137
138
  )
@@ -149,13 +150,14 @@ module RBS
149
150
  git('rev-parse', 'HEAD').chomp
150
151
  end
151
152
 
152
- private def git(*cmd)
153
- sh! 'git', *cmd
153
+ private def git(*cmd, **opt)
154
+ sh! 'git', *cmd, **opt
154
155
  end
155
156
 
156
- private def sh!(*cmd)
157
+ private def sh!(*cmd, **opt)
157
158
  RBS.logger.debug "$ #{cmd.join(' ')}"
158
- (__skip__ = Open3.capture3(*cmd, chdir: git_dir)).then do |out, err, status|
159
+ opt = { chdir: git_dir }.merge(opt).compact
160
+ (__skip__ = Open3.capture3(*cmd, **opt)).then do |out, err, status|
159
161
  raise CommandError, "Unexpected status #{status.exitstatus}\n\n#{err}" unless status.success?
160
162
 
161
163
  out
@@ -291,6 +291,10 @@ module RBS
291
291
  end
292
292
 
293
293
  one_ancestors.each_extended_module do |mod|
294
+ mod.args.each do |arg|
295
+ validate_type_presence(arg)
296
+ end
297
+
294
298
  mod_defn = build_instance(mod.name, no_self_types: true)
295
299
  merge_definition(src: mod_defn,
296
300
  dest: definition,
@@ -299,6 +303,10 @@ module RBS
299
303
 
300
304
  interface_methods = {}
301
305
  one_ancestors.each_extended_interface do |mod|
306
+ mod.args.each do |arg|
307
+ validate_type_presence(arg)
308
+ end
309
+
302
310
  mod_defn = build_interface(mod.name)
303
311
  subst = Substitution.build(mod_defn.type_params, mod.args)
304
312
 
@@ -781,9 +789,36 @@ module RBS
781
789
  end
782
790
 
783
791
  def expand_alias(type_name)
784
- entry = env.alias_decls[type_name] or raise "Unknown name for expand_alias: #{type_name}"
792
+ expand_alias2(type_name, [])
793
+ end
794
+
795
+ def expand_alias1(type_name)
796
+ entry = env.alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
797
+ as = entry.decl.type_params.each.map { Types::Bases::Any.new(location: nil) }
798
+ expand_alias2(type_name, as)
799
+ end
800
+
801
+ def expand_alias2(type_name, args)
802
+ entry = env.alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
803
+
785
804
  ensure_namespace!(type_name.namespace, location: entry.decl.location)
786
- entry.decl.type
805
+ params = entry.decl.type_params.each.map(&:name)
806
+
807
+ unless params.size == args.size
808
+ as = "[#{args.join(", ")}]" unless args.empty?
809
+ ps = "[#{params.join(", ")}]" unless params.empty?
810
+
811
+ raise "Invalid type application: type = #{type_name}#{as}, decl = #{type_name}#{ps}"
812
+ end
813
+
814
+ type = entry.decl.type
815
+
816
+ unless params.empty?
817
+ subst = Substitution.build(params, args)
818
+ type = type.sub(subst)
819
+ end
820
+
821
+ type
787
822
  end
788
823
 
789
824
  def update(env:, except:, ancestor_builder:)
@@ -804,5 +839,26 @@ module RBS
804
839
  end
805
840
  end
806
841
  end
842
+
843
+ def validate_type_presence(type)
844
+ case type
845
+ when Types::ClassInstance, Types::ClassSingleton, Types::Interface, Types::Alias
846
+ validate_type_name(type.name, type.location)
847
+ end
848
+
849
+ type.each_type do |type|
850
+ validate_type_presence(type)
851
+ end
852
+ end
853
+
854
+ def validate_type_name(name, location)
855
+ name = name.absolute!
856
+
857
+ return if name.class? && env.class_decls.key?(name)
858
+ return if name.interface? && env.interface_decls.key?(name)
859
+ return if name.alias? && env.alias_decls.key?(name)
860
+
861
+ raise NoTypeFoundError.new(type_name: name, location: location)
862
+ end
807
863
  end
808
864
  end
@@ -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.expand_alias(name), &block
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
@@ -13,6 +13,7 @@ begin
13
13
  filter = ENV.fetch('RBS_TEST_TARGET', "").split(',').map! { |e| e.strip }
14
14
  skips = (ENV['RBS_TEST_SKIP'] || '').split(',').map! { |e| e.strip }
15
15
  RBS.logger_level = (ENV["RBS_TEST_LOGLEVEL"] || "info")
16
+ logger.level = RBS.logger_level
16
17
  sample_size = get_sample_size(ENV['RBS_TEST_SAMPLE_SIZE'] || '')
17
18
  double_class = to_double_class(ENV['RBS_TEST_DOUBLE_SUITE'])
18
19
  unchecked_classes = (ENV['RBS_TEST_UNCHECKED_CLASSES'] || '').split(',').map! { |unchecked_class| unchecked_class.strip }.push(*double_class)