Feature #15575
closedProhibit to pass a block singleton class
Description
The following code works now:
def foo
class << Object.new
yield
end
end
foo{ p :ok } #=> :ok
but I think this feature is very strange because local variables are not active in singleton class.
How about to prohibit this feature?
plan: warning at ruby 2.7 and prohibit it in ruby 3.
Updated by Eregon (Benoit Daloze) over 5 years ago
Agreed.
IMHO class << expr
should be no different than the normal class Name
, but currently various things are allowed in that context such as return
, yield
, etc.
Constant resolution also becomes somewhat dynamically-scoped with class << expr
which is also a weird exception.
So longer term maybe it would be good to deprecate class <<
entirely and use singleton_class.class_exec do
instead.
Updated by ko1 (Koichi Sasada) over 5 years ago
Eregon (Benoit Daloze) wrote:
Agreed.
IMHOclass << expr
should be no different than the normalclass Name
, but currently various things are allowed in that context such asreturn
,yield
, etc.Constant resolution also becomes somewhat dynamically-scoped with
class << expr
which is also a weird exception.
So longer term maybe it would be good to deprecateclass <<
entirely and usesingleton_class.class_exec do
instead.
or make it syntax sugre of singleton_class.class_exec do
?
Both are easy to explain the rule. Now, it is somewhat unclear.
Updated by ko1 (Koichi Sasada) over 5 years ago
Similar strange example (off-topic):
1.times{
class C
break
def undefined_method; end
end
p :unrechable
}
p [:ok, C.instance_methods(false)] #=> [:ok, []]
We can break from class
syntax.
I hope nobody use it :(
Updated by Eregon (Benoit Daloze) over 5 years ago
ko1 (Koichi Sasada) wrote:
or make it syntax sugre of
singleton_class.class_exec do
?
I think that would be confusing as class
(like module
and def
) is a keyword which normally adds a new lexical scope and does not capture the parent local variables.
Updated by Eregon (Benoit Daloze) over 5 years ago
ko1 (Koichi Sasada) wrote:
We can break from
class
syntax.
I hope nobody use it :(
At least TruffleRuby doesn't implement it, and we had no bug report about this, so hopefully not used.
Agreed it should be deprecated/removed as it's confusing at best.
Updated by alanwu (Alan Wu) over 5 years ago
Another option would be to make everything use lexical scope, if the strangeness is indeed because locals are inaccessible inside class << self.
So imagine the following printing 1 2 3.
foo = 1
class A
bar = 2
def hi
baz = 3
class << self
p foo, bar, baz
end
end
end
A.new.hi
Is it less strange if everything used the same scoping rule?
Updated by matz (Yukihiro Matsumoto) over 5 years ago
Agreed to prohibit. Disagree to change the scoping rule (@alanwu (Alan Wu)).
Matz.
Updated by ko1 (Koichi Sasada) over 5 years ago
Matz, Thank you for confirmation.
I add a warning (without -w) like that:
def foo
class << Object.new
yield
end
end
foo{ p :ok } #=> :ok
test.rb: warning: `yield' in class syntax will not be supported from Ruby 3.0. [Feature #15575]
English correction is wlecome :)
Updated by ko1 (Koichi Sasada) over 5 years ago
- Status changed from Open to Closed
Applied in changeset trunk|r66999.
check and show a warning for incorrect yield.
- compile.c (check_yield_place): this function check the yield location.
-
show a warning if yield in
class
syntax. [Feature #15575] -
do strict check for toplevel
yield
. Without this patch,
1.times{ yield }
in toplevel is valid-syntax (raise LocalJumpError
at runtime) although toplevel simpleyield
is not valid syntax.
This patch make them syntax error.
-