rbs 1.7.1 → 2.0.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +104 -3
  3. data/core/array.rbs +3 -3
  4. data/core/builtin.rbs +4 -0
  5. data/core/enumerable.rbs +3 -3
  6. data/docs/collection.md +23 -1
  7. data/docs/syntax.md +117 -61
  8. data/ext/rbs_extension/constants.c +2 -6
  9. data/ext/rbs_extension/constants.h +1 -2
  10. data/ext/rbs_extension/parser.c +220 -184
  11. data/ext/rbs_extension/parserstate.c +6 -2
  12. data/ext/rbs_extension/parserstate.h +10 -0
  13. data/ext/rbs_extension/ruby_objs.c +17 -17
  14. data/ext/rbs_extension/ruby_objs.h +3 -4
  15. data/lib/rbs/ast/declarations.rb +6 -99
  16. data/lib/rbs/ast/type_param.rb +134 -0
  17. data/lib/rbs/cli.rb +33 -5
  18. data/lib/rbs/collection/config/lockfile_generator.rb +26 -18
  19. data/lib/rbs/collection/sources/git.rb +18 -7
  20. data/lib/rbs/collection/sources/rubygems.rb +7 -0
  21. data/lib/rbs/collection/sources/stdlib.rb +6 -0
  22. data/lib/rbs/definition.rb +9 -0
  23. data/lib/rbs/definition_builder.rb +78 -16
  24. data/lib/rbs/environment.rb +32 -8
  25. data/lib/rbs/environment_loader.rb +0 -2
  26. data/lib/rbs/environment_walker.rb +4 -1
  27. data/lib/rbs/errors.rb +31 -6
  28. data/lib/rbs/location_aux.rb +2 -0
  29. data/lib/rbs/method_type.rb +29 -6
  30. data/lib/rbs/prototype/rb.rb +3 -3
  31. data/lib/rbs/prototype/rbi.rb +8 -6
  32. data/lib/rbs/prototype/runtime.rb +4 -4
  33. data/lib/rbs/type_alias_regularity.rb +115 -0
  34. data/lib/rbs/types.rb +99 -22
  35. data/lib/rbs/validator.rb +99 -15
  36. data/lib/rbs/variance_calculator.rb +60 -31
  37. data/lib/rbs/version.rb +1 -1
  38. data/lib/rbs/writer.rb +2 -14
  39. data/lib/rbs.rb +2 -0
  40. data/schema/decls.json +19 -46
  41. data/schema/methodType.json +1 -1
  42. data/schema/typeParam.json +36 -0
  43. data/schema/types.json +8 -2
  44. data/sig/collection/collections.rbs +11 -2
  45. data/sig/collection/config.rbs +2 -2
  46. data/sig/declarations.rbs +15 -62
  47. data/sig/definition.rbs +11 -1
  48. data/sig/definition_builder.rbs +37 -1
  49. data/sig/environment.rbs +7 -1
  50. data/sig/environment_walker.rbs +26 -0
  51. data/sig/errors.rbs +28 -3
  52. data/sig/location.rbs +3 -1
  53. data/sig/locator.rbs +1 -1
  54. data/sig/method_types.rbs +25 -4
  55. data/sig/type_alias_regularity.rbs +92 -0
  56. data/sig/type_param.rbs +74 -0
  57. data/sig/types.rbs +37 -8
  58. data/sig/validator.rbs +38 -2
  59. data/sig/variance_calculator.rbs +50 -0
  60. data/sig/writer.rbs +1 -1
  61. data/stdlib/bigdecimal-math/0/manifest.yaml +2 -0
  62. data/stdlib/csv/0/manifest.yaml +2 -0
  63. data/stdlib/date/0/date.rbs +2 -2
  64. data/stdlib/logger/0/manifest.yaml +2 -0
  65. data/stdlib/net-http/0/manifest.yaml +2 -0
  66. data/stdlib/openssl/0/manifest.yaml +2 -0
  67. data/stdlib/prime/0/manifest.yaml +2 -0
  68. data/stdlib/resolv/0/manifest.yaml +3 -0
  69. data/stdlib/set/0/set.rbs +3 -3
  70. data/stdlib/uri/0/common.rbs +10 -5
  71. data/stdlib/uri/0/ftp.rbs +10 -0
  72. data/stdlib/uri/0/generic.rbs +34 -34
  73. data/stdlib/uri/0/mailto.rbs +5 -0
  74. data/stdlib/uri/0/ws.rbs +10 -0
  75. data/stdlib/uri/0/wss.rbs +7 -0
  76. data/stdlib/yaml/0/manifest.yaml +3 -0
  77. data/steep/Gemfile.lock +10 -10
  78. metadata +21 -4
@@ -4,103 +4,6 @@ module RBS
4
4
  class Base
5
5
  end
6
6
 
7
- class ModuleTypeParams
8
- attr_reader :params
9
-
10
- TypeParam = _ = Struct.new(:name, :variance, :skip_validation, :location, keyword_init: true) do
11
- # @implements TypeParam
12
-
13
- def to_json(state = _ = nil)
14
- {
15
- name: name,
16
- variance: variance,
17
- skip_validation: skip_validation,
18
- }.to_json(state)
19
- end
20
-
21
- def ==(other)
22
- other.is_a?(TypeParam) &&
23
- other.name == name &&
24
- other.variance == variance &&
25
- other.skip_validation == skip_validation
26
- end
27
-
28
- alias eql? ==
29
-
30
- def hash
31
- self.class.hash ^ name.hash ^ variance.hash ^ skip_validation.hash
32
- end
33
- end
34
-
35
- def initialize()
36
- @params = []
37
- end
38
-
39
- def add(param)
40
- params << param
41
- self
42
- end
43
-
44
- def ==(other)
45
- other.is_a?(ModuleTypeParams) && other.params == params
46
- end
47
-
48
- alias eql? ==
49
-
50
- def hash
51
- params.hash
52
- end
53
-
54
- def [](name)
55
- params.find {|p| p.name == name }
56
- end
57
-
58
- def to_json(state = _ = nil)
59
- {
60
- params: params
61
- }.to_json(state)
62
- end
63
-
64
- def each(&block)
65
- if block
66
- params.each(&block)
67
- else
68
- params.each
69
- end
70
- end
71
-
72
- def self.empty
73
- new
74
- end
75
-
76
- def variance(name)
77
- var = self[name] or raise
78
- var.variance
79
- end
80
-
81
- def skip_validation?(name)
82
- var = self[name] or raise
83
- var.skip_validation
84
- end
85
-
86
- def empty?
87
- params.empty?
88
- end
89
-
90
- def size
91
- params.size
92
- end
93
-
94
- def rename_to(names)
95
- ModuleTypeParams.new().tap do |params|
96
- names.each.with_index do |new_name, index|
97
- param = self.params[index]
98
- params.add(TypeParam.new(name: new_name, variance: param.variance, skip_validation: param.skip_validation, location: param.location))
99
- end
100
- end
101
- end
102
- end
103
-
104
7
  module NestedDeclarationHelper
105
8
  def each_member
106
9
  if block_given?
@@ -362,13 +265,15 @@ module RBS
362
265
 
363
266
  class Alias < Base
364
267
  attr_reader :name
268
+ attr_reader :type_params
365
269
  attr_reader :type
366
270
  attr_reader :annotations
367
271
  attr_reader :location
368
272
  attr_reader :comment
369
273
 
370
- def initialize(name:, type:, annotations:, location:, comment:)
274
+ def initialize(name:, type_params:, type:, annotations:, location:, comment:)
371
275
  @name = name
276
+ @type_params = type_params
372
277
  @type = type
373
278
  @annotations = annotations
374
279
  @location = location
@@ -378,19 +283,21 @@ module RBS
378
283
  def ==(other)
379
284
  other.is_a?(Alias) &&
380
285
  other.name == name &&
286
+ other.type_params == type_params &&
381
287
  other.type == type
382
288
  end
383
289
 
384
290
  alias eql? ==
385
291
 
386
292
  def hash
387
- self.class.hash ^ name.hash ^ type.hash
293
+ self.class.hash ^ name.hash ^ type_params.hash ^ type.hash
388
294
  end
389
295
 
390
296
  def to_json(state = _ = nil)
391
297
  {
392
298
  declaration: :alias,
393
299
  name: name,
300
+ type_params: type_params,
394
301
  type: type,
395
302
  annotations: annotations,
396
303
  location: location,
@@ -0,0 +1,134 @@
1
+ module RBS
2
+ module AST
3
+ class TypeParam
4
+ attr_reader :name, :variance, :location, :upper_bound
5
+
6
+ def initialize(name:, variance:, upper_bound:, location:)
7
+ @name = name
8
+ @variance = variance
9
+ @upper_bound = upper_bound
10
+ @location = location
11
+ @unchecked = false
12
+ end
13
+
14
+ def unchecked!(value = true)
15
+ @unchecked = value ? true : false
16
+ self
17
+ end
18
+
19
+ def unchecked?
20
+ @unchecked
21
+ end
22
+
23
+ def ==(other)
24
+ other.is_a?(TypeParam) &&
25
+ other.name == name &&
26
+ other.variance == variance &&
27
+ other.upper_bound == upper_bound &&
28
+ other.unchecked? == unchecked?
29
+ end
30
+
31
+ alias eql? ==
32
+
33
+ def hash
34
+ self.class.hash ^ name.hash ^ variance.hash ^ upper_bound.hash ^ unchecked?.hash
35
+ end
36
+
37
+ def to_json(state = JSON::State.new)
38
+ {
39
+ name: name,
40
+ variance: variance,
41
+ unchecked: unchecked?,
42
+ location: location,
43
+ upper_bound: upper_bound
44
+ }.to_json(state)
45
+ end
46
+
47
+ def rename(name)
48
+ TypeParam.new(
49
+ name: name,
50
+ variance: variance,
51
+ upper_bound: upper_bound,
52
+ location: location
53
+ ).unchecked!(unchecked?)
54
+ end
55
+
56
+ def map_type(&block)
57
+ if b = upper_bound
58
+ _upper_bound = yield(b)
59
+ end
60
+
61
+ TypeParam.new(
62
+ name: name,
63
+ variance: variance,
64
+ upper_bound: _upper_bound,
65
+ location: location
66
+ ).unchecked!(unchecked?)
67
+ end
68
+
69
+ def self.resolve_variables(params)
70
+ return if params.empty?
71
+
72
+ vars = Set.new(params.map(&:name))
73
+
74
+ params.map! do |param|
75
+ param.map_type {|bound| _ = subst_var(vars, bound) }
76
+ end
77
+ end
78
+
79
+ def self.subst_var(vars, type)
80
+ case type
81
+ when Types::ClassInstance
82
+ namespace = type.name.namespace
83
+ if namespace.relative? && namespace.empty? && vars.member?(type.name.name)
84
+ return Types::Variable.new(name: type.name.name, location: type.location)
85
+ end
86
+ end
87
+
88
+ type.map_type {|t| subst_var(vars, t) }
89
+ end
90
+
91
+ def self.rename(params, new_names:)
92
+ raise unless params.size == new_names.size
93
+
94
+ subst = Substitution.build(new_names, Types::Variable.build(new_names))
95
+
96
+ params.map.with_index do |param, index|
97
+ new_name = new_names[index]
98
+
99
+ TypeParam.new(
100
+ name: new_name,
101
+ variance: param.variance,
102
+ upper_bound: param.upper_bound&.map_type {|type| type.sub(subst) },
103
+ location: param.location
104
+ ).unchecked!(param.unchecked?)
105
+ end
106
+ end
107
+
108
+ def to_s
109
+ s = ""
110
+
111
+ if unchecked?
112
+ s << "unchecked "
113
+ end
114
+
115
+ case variance
116
+ when :invariant
117
+ # nop
118
+ when :covariant
119
+ s << "out "
120
+ when :contravariant
121
+ s << "in "
122
+ end
123
+
124
+ s << name.to_s
125
+
126
+ if type = upper_bound
127
+ s << " < #{type}"
128
+ end
129
+
130
+ s
131
+ end
132
+ end
133
+ end
134
+ end
data/lib/rbs/cli.rb CHANGED
@@ -430,7 +430,7 @@ EOU
430
430
  builder = DefinitionBuilder.new(env: env)
431
431
  validator = Validator.new(env: env, resolver: TypeNameResolver.from_env(env))
432
432
 
433
- env.class_decls.each_key do |name|
433
+ env.class_decls.each do |name, decl|
434
434
  stdout.puts "Validating class/module definition: `#{name}`..."
435
435
  builder.build_instance(name).each_type do |type|
436
436
  validator.validate_type type, context: [Namespace.root]
@@ -438,13 +438,43 @@ EOU
438
438
  builder.build_singleton(name).each_type do |type|
439
439
  validator.validate_type type, context: [Namespace.root]
440
440
  end
441
+
442
+ d = decl.primary.decl
443
+
444
+ validator.validate_type_params(
445
+ d.type_params,
446
+ type_name: name,
447
+ location: d.location&.aref(:type_params)
448
+ )
449
+
450
+ decl.decls.each do |d|
451
+ d.decl.each_member do |member|
452
+ case member
453
+ when AST::Members::MethodDefinition
454
+ validator.validate_method_definition(member, type_name: name)
455
+ end
456
+ end
457
+ end
441
458
  end
442
459
 
443
- env.interface_decls.each_key do |name|
460
+ env.interface_decls.each do |name, decl|
444
461
  stdout.puts "Validating interface: `#{name}`..."
445
462
  builder.build_interface(name).each_type do |type|
446
463
  validator.validate_type type, context: [Namespace.root]
447
464
  end
465
+
466
+ validator.validate_type_params(
467
+ decl.decl.type_params,
468
+ type_name: name,
469
+ location: decl.decl.location&.aref(:type_params)
470
+ )
471
+
472
+ decl.decl.members.each do |member|
473
+ case member
474
+ when AST::Members::MethodDefinition
475
+ validator.validate_method_definition(member, type_name: name)
476
+ end
477
+ end
448
478
  end
449
479
 
450
480
  env.constant_decls.each do |name, const|
@@ -460,7 +490,7 @@ EOU
460
490
 
461
491
  env.alias_decls.each do |name, decl|
462
492
  stdout.puts "Validating alias: `#{name}`..."
463
- builder.expand_alias(name).tap do |type|
493
+ builder.expand_alias1(name).tap do |type|
464
494
  validator.validate_type type, context: [Namespace.root]
465
495
  end
466
496
  validator.validate_type_alias(entry: decl)
@@ -836,8 +866,6 @@ EOB
836
866
  end
837
867
 
838
868
  def run_collection(args, options)
839
- warn "warning: rbs collection is experimental, and the behavior may change until RBS v2.0"
840
-
841
869
  opts = collection_options(args)
842
870
  params = {}
843
871
  opts.order args.drop(1), into: params
@@ -15,15 +15,20 @@ module RBS
15
15
  @lock_path = Config.to_lockfile_path(config_path)
16
16
  @lock = Config.from_path(lock_path) if lock_path.exist? && with_lockfile
17
17
  @gemfile_lock = Bundler::LockfileParser.new(gemfile_lock_path.read)
18
+ @gem_queue = []
18
19
  end
19
20
 
20
21
  def generate
21
22
  config.gems.each do |gem|
22
- assign_gem(gem_name: gem['name'], version: gem['version'])
23
+ @gem_queue.push({ name: gem['name'], version: gem['version'] })
23
24
  end
24
25
 
25
26
  gemfile_lock_gems do |spec|
26
- assign_gem(gem_name: spec.name, version: spec.version)
27
+ @gem_queue.push({ name: spec.name, version: spec.version })
28
+ end
29
+
30
+ while gem = @gem_queue.shift
31
+ assign_gem(**gem)
27
32
  end
28
33
  remove_ignored_gems!
29
34
 
@@ -31,30 +36,33 @@ module RBS
31
36
  config
32
37
  end
33
38
 
34
- private def assign_gem(gem_name:, version:)
35
- locked = lock&.gem(gem_name)
36
- specified = config.gem(gem_name)
39
+ private def assign_gem(name:, version:)
40
+ locked = lock&.gem(name)
41
+ specified = config.gem(name)
37
42
 
38
43
  return if specified&.dig('ignore')
39
44
  return if specified&.dig('source') # skip if the source is already filled
40
45
 
41
- if locked
42
- # If rbs_collection.lock.yaml contain the gem, use it.
43
- upsert_gem specified, locked
44
- else
45
- # Find the gem from gem_collection.
46
- source = find_source(gem_name: gem_name)
46
+ # If rbs_collection.lock.yaml contain the gem, use it.
47
+ # Else find the gem from gem_collection.
48
+ unless locked
49
+ source = find_source(name: name)
47
50
  return unless source
48
51
 
49
52
  installed_version = version
50
- best_version = find_best_version(version: installed_version, versions: source.versions({ 'name' => gem_name }))
51
- # @type var new_content: RBS::Collection::Config::gem_entry
52
- new_content = {
53
- 'name' => gem_name,
53
+ best_version = find_best_version(version: installed_version, versions: source.versions({ 'name' => name }))
54
+ locked = {
55
+ 'name' => name,
54
56
  'version' => best_version.to_s,
55
57
  'source' => source.to_lockfile,
56
58
  }
57
- upsert_gem specified, new_content
59
+ end
60
+
61
+ upsert_gem specified, locked
62
+ source = Sources.from_config_entry(locked['source'])
63
+ manifest = source.manifest_of(locked) or return
64
+ manifest['dependencies']&.each do |dep|
65
+ @gem_queue.push({ name: dep['name'], version: nil} )
58
66
  end
59
67
  end
60
68
 
@@ -76,10 +84,10 @@ module RBS
76
84
  end
77
85
  end
78
86
 
79
- private def find_source(gem_name:)
87
+ private def find_source(name:)
80
88
  sources = config.sources
81
89
 
82
- sources.find { |c| c.has?({ 'name' => gem_name, 'revision' => nil } ) }
90
+ sources.find { |c| c.has?({ 'name' => name, 'revision' => nil } ) }
83
91
  end
84
92
 
85
93
  private def find_best_version(version:, versions:)
@@ -50,6 +50,15 @@ module RBS
50
50
  end
51
51
  end
52
52
 
53
+ def manifest_of(config_entry)
54
+ gem_name = config_entry['name']
55
+ version = config_entry['version'] or raise
56
+ gem_dir = gem_repo_dir.join(gem_name, version)
57
+
58
+ manifest_path = gem_dir.join('manifest.yaml')
59
+ YAML.safe_load(manifest_path.read) if manifest_path.exist?
60
+ end
61
+
53
62
  private def _install(dest:, config_entry:)
54
63
  gem_name = config_entry['name']
55
64
  version = config_entry['version'] or raise
@@ -104,9 +113,9 @@ module RBS
104
113
  else
105
114
  begin
106
115
  # git v2.27.0 or greater
107
- git 'clone', '--filter=blob:none', remote, git_dir.to_s
116
+ git 'clone', '--filter=blob:none', remote, git_dir.to_s, chdir: nil
108
117
  rescue CommandError
109
- git 'clone', remote, git_dir.to_s
118
+ git 'clone', remote, git_dir.to_s, chdir: nil
110
119
  end
111
120
  end
112
121
 
@@ -131,7 +140,8 @@ module RBS
131
140
  private def git_dir
132
141
  @git_dir ||= (
133
142
  base = Pathname(ENV['XDG_CACHE_HOME'] || File.expand_path("~/.cache"))
134
- dir = base.join('rbs', Digest::SHA256.hexdigest(remote))
143
+ cache_key = remote.start_with?('.') ? "#{remote}\0#{Dir.pwd}" : remote
144
+ dir = base.join('rbs', Digest::SHA256.hexdigest(cache_key))
135
145
  dir.mkpath
136
146
  dir
137
147
  )
@@ -149,13 +159,14 @@ module RBS
149
159
  git('rev-parse', 'HEAD').chomp
150
160
  end
151
161
 
152
- private def git(*cmd)
153
- sh! 'git', *cmd
162
+ private def git(*cmd, **opt)
163
+ sh! 'git', *cmd, **opt
154
164
  end
155
165
 
156
- private def sh!(*cmd)
166
+ private def sh!(*cmd, **opt)
157
167
  RBS.logger.debug "$ #{cmd.join(' ')}"
158
- (__skip__ = Open3.capture3(*cmd, chdir: git_dir)).then do |out, err, status|
168
+ opt = { chdir: git_dir }.merge(opt).compact
169
+ (__skip__ = Open3.capture3(*cmd, **opt)).then do |out, err, status|
159
170
  raise CommandError, "Unexpected status #{status.exitstatus}\n\n#{err}" unless status.success?
160
171
 
161
172
  out
@@ -25,6 +25,13 @@ module RBS
25
25
  stdout.puts "Using #{name}:#{version} (#{from})"
26
26
  end
27
27
 
28
+ def manifest_of(config_entry)
29
+ _, sig_path = gem_sig_path(config_entry)
30
+ sig_path or raise
31
+ manifest_path = sig_path.join('manifest.yaml')
32
+ YAML.safe_load(manifest_path.read) if manifest_path.exist?
33
+ end
34
+
28
35
  def to_lockfile
29
36
  {
30
37
  'type' => 'rubygems',
@@ -23,6 +23,12 @@ module RBS
23
23
  stdout.puts "Using #{name}:#{version} (#{from})"
24
24
  end
25
25
 
26
+ def manifest_of(config_entry)
27
+ version = config_entry['version'] or raise
28
+ manifest_path = gem_dir(config_entry).join(version, 'manifest.yaml')
29
+ YAML.safe_load(manifest_path.read) if manifest_path.exist?
30
+ end
31
+
26
32
  def to_lockfile
27
33
  {
28
34
  'type' => 'stdlib',
@@ -155,6 +155,15 @@ module RBS
155
155
  )
156
156
  end
157
157
 
158
+ def map_type_bound(&block)
159
+ self.class.new(
160
+ super_method: super_method&.map_type_bound(&block),
161
+ defs: defs.map {|defn| defn.update(type: defn.type.map_type_bound(&block)) },
162
+ accessibility: @accessibility,
163
+ alias_of: alias_of
164
+ )
165
+ end
166
+
158
167
  def map_method_type(&block)
159
168
  self.class.new(
160
169
  super_method: super_method,
@@ -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
 
@@ -377,7 +385,7 @@ module RBS
377
385
  initialize = instance.methods[:initialize]
378
386
 
379
387
  if initialize
380
- class_params = entry.type_params.each.map(&:name)
388
+ class_params = entry.type_params
381
389
 
382
390
  # Inject a virtual _typed new_.
383
391
  initialize_defs = initialize.defs
@@ -386,28 +394,34 @@ module RBS
386
394
  defs: initialize_defs.map do |initialize_def|
387
395
  method_type = initialize_def.type
388
396
 
389
- class_type_param_vars = Set.new(class_params)
390
- method_type_param_vars = Set.new(method_type.type_params)
397
+ class_type_param_vars = Set.new(class_params.map(&:name))
398
+ method_type_param_vars = Set.new(method_type.type_params.map(&:name))
391
399
 
392
400
  if class_type_param_vars.intersect?(method_type_param_vars)
393
- renamed_method_params = method_type.type_params.map do |name|
394
- if class_type_param_vars.include?(name)
395
- Types::Variable.fresh(name).name
401
+ new_method_param_names = method_type.type_params.map do |method_param|
402
+ if class_type_param_vars.include?(method_param.name)
403
+ Types::Variable.fresh(method_param.name).name
396
404
  else
397
- name
405
+ method_param.name
398
406
  end
399
407
  end
400
- method_params = class_params + renamed_method_params
401
408
 
402
- sub = Substitution.build(method_type.type_params, Types::Variable.build(renamed_method_params))
409
+ sub = Substitution.build(
410
+ method_type.type_params.map(&:name),
411
+ Types::Variable.build(new_method_param_names)
412
+ )
413
+
414
+ method_params = class_params + AST::TypeParam.rename(method_type.type_params, new_names: new_method_param_names)
415
+ method_type = method_type
416
+ .update(type_params: [])
417
+ .sub(sub)
418
+ .update(type_params: method_params)
403
419
  else
404
- method_params = class_params + method_type.type_params
405
- sub = Substitution.build([], [])
420
+ method_type = method_type
421
+ .update(type_params: class_params + method_type.type_params)
406
422
  end
407
423
 
408
- method_type = method_type.map_type {|ty| ty.sub(sub) }
409
424
  method_type = method_type.update(
410
- type_params: method_params,
411
425
  type: method_type.type.with_return_type(
412
426
  Types::ClassInstance.new(
413
427
  name: type_name,
@@ -438,7 +452,7 @@ module RBS
438
452
 
439
453
  def validate_params_with(type_params, result:)
440
454
  type_params.each do |param|
441
- unless param.skip_validation
455
+ unless param.unchecked?
442
456
  unless result.compatible?(param.name, with_annotation: param.variance)
443
457
  yield param
444
458
  end
@@ -781,9 +795,36 @@ module RBS
781
795
  end
782
796
 
783
797
  def expand_alias(type_name)
784
- entry = env.alias_decls[type_name] or raise "Unknown name for expand_alias: #{type_name}"
798
+ expand_alias2(type_name, [])
799
+ end
800
+
801
+ def expand_alias1(type_name)
802
+ entry = env.alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
803
+ as = entry.decl.type_params.each.map { Types::Bases::Any.new(location: nil) }
804
+ expand_alias2(type_name, as)
805
+ end
806
+
807
+ def expand_alias2(type_name, args)
808
+ entry = env.alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
809
+
785
810
  ensure_namespace!(type_name.namespace, location: entry.decl.location)
786
- entry.decl.type
811
+ params = entry.decl.type_params.each.map(&:name)
812
+
813
+ unless params.size == args.size
814
+ as = "[#{args.join(", ")}]" unless args.empty?
815
+ ps = "[#{params.join(", ")}]" unless params.empty?
816
+
817
+ raise "Invalid type application: type = #{type_name}#{as}, decl = #{type_name}#{ps}"
818
+ end
819
+
820
+ type = entry.decl.type
821
+
822
+ unless params.empty?
823
+ subst = Substitution.build(params, args)
824
+ type = type.sub(subst)
825
+ end
826
+
827
+ type
787
828
  end
788
829
 
789
830
  def update(env:, except:, ancestor_builder:)
@@ -804,5 +845,26 @@ module RBS
804
845
  end
805
846
  end
806
847
  end
848
+
849
+ def validate_type_presence(type)
850
+ case type
851
+ when Types::ClassInstance, Types::ClassSingleton, Types::Interface, Types::Alias
852
+ validate_type_name(type.name, type.location)
853
+ end
854
+
855
+ type.each_type do |type|
856
+ validate_type_presence(type)
857
+ end
858
+ end
859
+
860
+ def validate_type_name(name, location)
861
+ name = name.absolute!
862
+
863
+ return if name.class? && env.class_decls.key?(name)
864
+ return if name.interface? && env.interface_decls.key?(name)
865
+ return if name.alias? && env.alias_decls.key?(name)
866
+
867
+ raise NoTypeFoundError.new(type_name: name, location: location)
868
+ end
807
869
  end
808
870
  end