Skip to content

Commit 3aea23c

Browse files
committed
class/instance type is rejected depending on the context
This is a Follow-up to #2590
1 parent b6693d8 commit 3aea23c

File tree

13 files changed

+385
-267
lines changed

13 files changed

+385
-267
lines changed

Rakefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ end
187187
task :validate => :compile do
188188
require 'yaml'
189189

190-
sh "#{ruby} #{rbs} validate --exit-error-on-syntax-error"
190+
sh "#{ruby} #{rbs} validate"
191191

192192
libs = FileList["stdlib/*"].map {|path| File.basename(path).to_s }
193193

@@ -208,7 +208,7 @@ task :validate => :compile do
208208
end
209209

210210
libs.each do |lib|
211-
sh "#{ruby} #{rbs} -r #{lib} validate --exit-error-on-syntax-error"
211+
sh "#{ruby} #{rbs} -r #{lib} validate"
212212
end
213213
end
214214

ext/rbs_extension/main.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ struct parse_type_arg {
8787
VALUE require_eof;
8888
VALUE void_allowed;
8989
VALUE self_allowed;
90+
VALUE classish_allowed;
9091
};
9192

9293
struct parse_method_type_arg {
@@ -118,9 +119,10 @@ static VALUE parse_type_try(VALUE a) {
118119

119120
bool void_allowed = RTEST(arg->void_allowed);
120121
bool self_allowed = RTEST(arg->self_allowed);
122+
bool classish_allowed = RTEST(arg->classish_allowed);
121123

122124
rbs_node_t *type;
123-
rbs_parse_type(parser, &type, void_allowed, self_allowed);
125+
rbs_parse_type(parser, &type, void_allowed, self_allowed, classish_allowed);
124126

125127
raise_error_if_any(parser, arg->buffer);
126128

@@ -176,7 +178,7 @@ static rbs_parser_t *alloc_parser_from_buffer(VALUE buffer, int start_pos, int e
176178
);
177179
}
178180

179-
static VALUE rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof, VALUE void_allowed, VALUE self_allowed) {
181+
static VALUE rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof, VALUE void_allowed, VALUE self_allowed, VALUE classish_allowed) {
180182
VALUE string = rb_funcall(buffer, rb_intern("content"), 0);
181183
StringValue(string);
182184
rb_encoding *encoding = rb_enc_get(string);
@@ -189,7 +191,8 @@ static VALUE rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VAL
189191
.parser = parser,
190192
.require_eof = require_eof,
191193
.void_allowed = void_allowed,
192-
.self_allowed = self_allowed
194+
.self_allowed = self_allowed,
195+
.classish_allowed = classish_allowed
193196
};
194197

195198
VALUE result = rb_ensure(parse_type_try, (VALUE) &arg, ensure_free_parser, (VALUE) parser);
@@ -208,7 +211,7 @@ static VALUE parse_method_type_try(VALUE a) {
208211
}
209212

210213
rbs_method_type_t *method_type = NULL;
211-
rbs_parse_method_type(parser, &method_type);
214+
rbs_parse_method_type(parser, &method_type, true);
212215

213216
raise_error_if_any(parser, arg->buffer);
214217

@@ -453,7 +456,7 @@ void rbs__init_parser(void) {
453456
VALUE empty_array = rb_obj_freeze(rb_ary_new());
454457
rb_gc_register_mark_object(empty_array);
455458

456-
rb_define_singleton_method(RBS_Parser, "_parse_type", rbsparser_parse_type, 7);
459+
rb_define_singleton_method(RBS_Parser, "_parse_type", rbsparser_parse_type, 8);
457460
rb_define_singleton_method(RBS_Parser, "_parse_method_type", rbsparser_parse_method_type, 5);
458461
rb_define_singleton_method(RBS_Parser, "_parse_signature", rbsparser_parse_signature, 3);
459462
rb_define_singleton_method(RBS_Parser, "_parse_type_params", rbsparser_parse_type_params, 4);

include/rbs/parser.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ rbs_ast_comment_t *rbs_parser_get_comment(rbs_parser_t *parser, int subject_line
126126

127127
void rbs_parser_set_error(rbs_parser_t *parser, rbs_token_t tok, bool syntax_error, const char *fmt, ...) RBS_ATTRIBUTE_FORMAT(4, 5);
128128

129-
bool rbs_parse_type(rbs_parser_t *parser, rbs_node_t **type, bool void_allowed, bool self_allowed);
130-
bool rbs_parse_method_type(rbs_parser_t *parser, rbs_method_type_t **method_type);
129+
bool rbs_parse_type(rbs_parser_t *parser, rbs_node_t **type, bool void_allowed, bool self_allowed, bool classish_allowed);
130+
bool rbs_parse_method_type(rbs_parser_t *parser, rbs_method_type_t **method_type, bool classish_allowed);
131131
bool rbs_parse_signature(rbs_parser_t *parser, rbs_signature_t **signature);
132132

133133
bool rbs_parse_type_params(rbs_parser_t *parser, bool module_type_params, rbs_node_list_t **params);

lib/rbs/cli/validate.rb

Lines changed: 5 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,13 @@ module RBS
44
class CLI
55
class Validate
66
class Errors
7-
def initialize(limit:, exit_error:)
7+
def initialize(limit:)
88
@limit = limit
9-
@exit_error = exit_error
109
@errors = []
11-
@has_syntax_error = false
1210
end
1311

1412
def add(error)
15-
if error.instance_of?(WillSyntaxError)
16-
RBS.logger.warn(build_message(error))
17-
@has_syntax_error = true
18-
else
19-
@errors << error
20-
end
13+
@errors << error
2114
finish if @limit == 1
2215
end
2316

@@ -30,13 +23,7 @@ def try(&block)
3023
end
3124

3225
def finish
33-
if @errors.empty?
34-
if @exit_error && @has_syntax_error
35-
throw @tag, 1
36-
else
37-
# success
38-
end
39-
else
26+
unless @errors.empty?
4027
@errors.each do |error|
4128
RBS.logger.error(build_message(error))
4229
end
@@ -63,7 +50,6 @@ def initialize(args:, options:)
6350
@env = Environment.from_loader(loader).resolve_type_names
6451
@builder = DefinitionBuilder.new(env: @env)
6552
@validator = Validator.new(env: @env)
66-
exit_error = false
6753
limit = nil #: Integer?
6854
OptionParser.new do |opts|
6955
opts.banner = <<EOU
@@ -80,14 +66,14 @@ def initialize(args:, options:)
8066
RBS.print_warning { "`--silent` option is deprecated because it's silent by default. You can use --log-level option of rbs command to display more information." }
8167
end
8268
opts.on("--[no-]exit-error-on-syntax-error", "exit(1) if syntax error is detected") {|bool|
83-
exit_error = bool
69+
RBS.print_warning { "`--exit-error-on-syntax-error` option is deprecated because it's validated during parsing.." }
8470
}
8571
opts.on("--fail-fast", "Exit immediately as soon as a validation error is found.") do |arg|
8672
limit = 1
8773
end
8874
end.parse!(args)
8975

90-
@errors = Errors.new(limit: limit, exit_error: exit_error)
76+
@errors = Errors.new(limit: limit)
9177
end
9278

9379
def run
@@ -122,7 +108,6 @@ def validate_class_module_definition
122108
entry.each_decl do |decl|
123109
if super_class = decl.super_class
124110
super_class.args.each do |arg|
125-
no_classish_type_validator(arg)
126111
@validator.validate_type(arg, context: nil)
127112
end
128113
end
@@ -131,7 +116,6 @@ def validate_class_module_definition
131116
entry.each_decl do |decl|
132117
decl.self_types.each do |self_type|
133118
self_type.args.each do |arg|
134-
no_classish_type_validator(arg)
135119
@validator.validate_type(arg, context: nil)
136120
end
137121

@@ -159,17 +143,14 @@ def validate_class_module_definition
159143

160144
d.type_params.each do |param|
161145
if ub = param.upper_bound_type
162-
no_classish_type_validator(ub)
163146
@validator.validate_type(ub, context: nil)
164147
end
165148

166149
if lb = param.lower_bound_type
167-
no_classish_type_validator(lb)
168150
@validator.validate_type(lb, context: nil)
169151
end
170152

171153
if dt = param.default_type
172-
no_classish_type_validator(dt)
173154
@validator.validate_type(dt, context: nil)
174155
end
175156
end
@@ -230,17 +211,14 @@ def validate_interface
230211

231212
decl.decl.type_params.each do |param|
232213
if ub = param.upper_bound_type
233-
no_classish_type_validator(ub)
234214
@validator.validate_type(ub, context: nil)
235215
end
236216

237217
if lb = param.lower_bound_type
238-
no_classish_type_validator(lb)
239218
@validator.validate_type(lb, context: nil)
240219
end
241220

242221
if dt = param.default_type
243-
no_classish_type_validator(dt)
244222
@validator.validate_type(dt, context: nil)
245223
end
246224
end
@@ -251,9 +229,6 @@ def validate_interface
251229
case member
252230
when AST::Members::MethodDefinition
253231
@validator.validate_method_definition(member, type_name: name)
254-
member.overloads.each do |ov|
255-
no_classish_type_validator(ov.method_type)
256-
end
257232
end
258233
end
259234
rescue BaseError => error
@@ -266,7 +241,6 @@ def validate_constant
266241
RBS.logger.info "Validating constant: `#{name}`..."
267242
@validator.validate_type const.decl.type, context: const.context
268243
@builder.ensure_namespace!(name.namespace, location: const.decl.location)
269-
no_classish_type_validator(const.decl.type)
270244
rescue BaseError => error
271245
@errors.add(error)
272246
end
@@ -276,7 +250,6 @@ def validate_global
276250
@env.global_decls.each do |name, global|
277251
RBS.logger.info "Validating global: `#{name}`..."
278252
@validator.validate_type global.decl.type, context: nil
279-
no_classish_type_validator(global.decl.type)
280253
rescue BaseError => error
281254
@errors.add(error)
282255
end
@@ -299,51 +272,23 @@ def validate_type_alias
299272

300273
decl.decl.type_params.each do |param|
301274
if ub = param.upper_bound_type
302-
no_classish_type_validator(ub)
303275
@validator.validate_type(ub, context: nil)
304276
end
305277

306278
if lb = param.lower_bound_type
307-
no_classish_type_validator(lb)
308279
@validator.validate_type(lb, context: nil)
309280
end
310281

311282
if dt = param.default_type
312-
no_classish_type_validator(dt)
313283
@validator.validate_type(dt, context: nil)
314284
end
315285
end
316286

317287
TypeParamDefaultReferenceError.check!(decl.decl.type_params)
318-
319-
no_classish_type_validator(decl.decl.type)
320288
rescue BaseError => error
321289
@errors.add(error)
322290
end
323291
end
324-
325-
private
326-
327-
def no_self_type_validator(type)
328-
if type.has_self_type?
329-
@errors.add WillSyntaxError.new("`self` type is not allowed in this context", location: type.location)
330-
end
331-
end
332-
333-
def no_classish_type_validator(type)
334-
if type.has_classish_type?
335-
@errors.add WillSyntaxError.new("`instance` or `class` type is not allowed in this context", location: type.location)
336-
end
337-
end
338-
339-
def void_type_context_validator(type, allowed_here = false)
340-
if allowed_here
341-
return if type.is_a?(Types::Bases::Void)
342-
end
343-
if type.with_nonreturn_void? # steep:ignore DeprecatedReference
344-
@errors.add WillSyntaxError.new("`void` type is only allowed in return type or generics parameter", location: type.location)
345-
end
346-
end
347292
end
348293
end
349294
end

lib/rbs/errors.rb

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ def self.check!(type_name:, env:, member:)
491491
else
492492
raise "Unknown member type: #{member.class}"
493493
end
494-
494+
495495
if env.class_decl?(name)
496496
raise new(type_name: type_name, member: member)
497497
end
@@ -611,17 +611,6 @@ def location
611611
end
612612
end
613613

614-
class WillSyntaxError < DefinitionError
615-
include DetailedMessageable
616-
617-
attr_reader :location
618-
619-
def initialize(message, location:)
620-
super "#{Location.to_string(location)}: #{message}"
621-
@location = location
622-
end
623-
end
624-
625614
class TypeParamDefaultReferenceError < DefinitionError
626615
include DetailedMessageable
627616

lib/rbs/parser_aux.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55

66
module RBS
77
class Parser
8-
def self.parse_type(source, range: 0..., variables: [], require_eof: false, void_allowed: true, self_allowed: true)
8+
def self.parse_type(source, range: 0..., variables: [], require_eof: false, void_allowed: true, self_allowed: true, classish_allowed: true)
99
buf = buffer(source)
10-
_parse_type(buf, range.begin || 0, range.end || buf.last_position, variables, require_eof, void_allowed, self_allowed)
10+
_parse_type(buf, range.begin || 0, range.end || buf.last_position, variables, require_eof, void_allowed, self_allowed, classish_allowed)
1111
end
1212

1313
def self.parse_method_type(source, range: 0..., variables: [], require_eof: false)

sig/cli/validate.rbs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@ module RBS
33
class Validate
44
class Errors
55
@limit: Integer?
6-
@exit_error: boolish
7-
@has_syntax_error: bool
86
@errors: Array[BaseError]
97

108
# The tag that will be thrown in #finish method
119
@tag: top
1210

13-
def initialize: (limit: Integer?, exit_error: boolish) -> void
11+
def initialize: (limit: Integer?) -> void
1412

1513
def add: (BaseError) -> void
1614

@@ -44,9 +42,6 @@ module RBS
4442
def validate_constant: () -> void
4543
def validate_global: () -> void
4644
def validate_type_alias: () -> void
47-
def no_classish_type_validator: (::RBS::Types::t | ::RBS::MethodType type) -> void
48-
def no_self_type_validator: (::RBS::Types::t | ::RBS::MethodType type) -> void
49-
%a{deprecated} def void_type_context_validator: (::RBS::Types::t | ::RBS::MethodType type, ?bool allowed_here) -> void
5045
end
5146
end
5247
end

sig/errors.rbs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -394,14 +394,6 @@ module RBS
394394
def location: () -> AST::Declarations::AliasDecl::loc?
395395
end
396396

397-
class WillSyntaxError < BaseError
398-
include RBS::DetailedMessageable
399-
400-
def initialize: (String message, location: Location[untyped, untyped]?) -> void
401-
402-
attr_reader location: Location[untyped, untyped]?
403-
end
404-
405397
class TypeParamDefaultReferenceError < BaseError
406398
include DetailedMessageable
407399

sig/parser.rbs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ module RBS
7676
# RBS::Parser.parse_type("self", self_allowed: false) # => Raises an syntax error
7777
# ```
7878
#
79-
def self.parse_type: (Buffer | String, ?range: Range[Integer?], ?variables: Array[Symbol], ?require_eof: bool, ?void_allowed: bool, ?self_allowed: bool) -> Types::t?
79+
def self.parse_type: (Buffer | String, ?range: Range[Integer?], ?variables: Array[Symbol], ?require_eof: bool, ?void_allowed: bool, ?self_allowed: bool, ?classish_allowed: bool) -> Types::t?
8080

8181
# Parse whole RBS file and return an array of declarations
8282
#
@@ -130,7 +130,7 @@ module RBS
130130

131131
def self.buffer: (String | Buffer source) -> Buffer
132132

133-
def self._parse_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof, bool void_allowed, bool self_allowed) -> Types::t?
133+
def self._parse_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof, bool void_allowed, bool self_allowed, bool classish_allowed) -> Types::t?
134134

135135
def self._parse_method_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof) -> MethodType?
136136

0 commit comments

Comments
 (0)