[ruby-core:114362] [Ruby master Feature#19832] Method#destructive?, UnboundMethod#destructive?
From:
janosch-x via ruby-core <ruby-core@...>
Date:
2023-08-08 20:32:40 UTC
List:
ruby-core #114362
Issue #19832 has been updated by janosch-x (Janosch M=FCller).
Dan0042 (Daniel DeLorme) wrote in #note-10:
> For regular ruby code, probably the only way to know if a method is destr=
uctive is to check for instance variable assignments.
A lot of everyday Ruby code seems to be destructive, not so much by setting=
instance variables, but rather by modifying them (e.g. Arrays or Hashes). =
> It's almost certainly impossible to propagate the 'destructive' flag tran=
sitively (#foo would be considered non-destructive even if it calls #bar de=
structive method).
You mean it would be impossible at load time? Maybe it's worth exploring a =
"static analysis" variant of this feature? Could it be tied in to RBS? Such=
an approach might allow for transitivity, which would make it much easier =
to provide this information for most existing code outside the stdlib. I gu=
ess these generated method attributes would still need to be able to change=
at runtime, e.g. in case of method overrides, and these changes would need=
to be propagated down all known call chains. (Using `send` and such might =
need to propagate `unknown` destructiveness down all call chains.)
Without transitivity, this feature might still be nice for inspecting the s=
tdlib, adding visual hints to the docs etc.
@sawa Did you have a particular use case in mind for this feature?=20
----------------------------------------
Feature #19832: Method#destructive?, UnboundMethod#destructive?
https://bugs.ruby-lang.org/issues/19832#change-104105
* Author: sawa (Tsuyoshi Sawada)
* Status: Open
* Priority: Normal
----------------------------------------
I propose to add `destructive?` property to `Method` and `UnboundMethod` in=
stances, which shall behave like:
```ruby
String.instance_method(:<<).destructive? # =3D> true
String.instance_method(:+).destructive? # =3D> false
```
One main purpose of using these classes is to inspect and make sure how a c=
ertain method behaves. Besides arity and owner, whether a method is destruc=
tive or not is one important piece of information, but currently, you canno=
t achieve that from `Method` or `UnboundMethod` instances.
The problem is how to implement this. It is best if this information (wheth=
er or not a method is destructive) can be extracted automatically from the =
method definition.
Unlike owner and arity, it may or may not be straightforward by statically =
analyzing the code. I think that, if a method definition defined at the rub=
y level does not call a destructive method anywhere within its own definiti=
on, and no dynamic method calls (`send`, `eval`, etc.) are made, then we ca=
n say that the method is non-destructive. If it does call, then the method =
is most likely a destructive method (it would not be destructive if the int=
ernally-called destructive method is applied to a different object. Or, we =
could rather call that a destructive method in the sense that it has a dest=
ructive side effect).
If doing that turns out to be difficult for some or all cases, then a pract=
ical approach for the difficult cases is to label the methods as destructiv=
e or not, manually. We can perhaps have methods `Module#destructive` and `M=
odule#non_destructive` which take (a) symbol/string argument(s) and return =
the method name(s) in symbol so that they can be used like:
```ruby
class A
destructive private def some_destructive_private_method
...
end
end
```
or
```ruby
class A
def foo; ... end
def bar; ... end
def baz; ... end
non_destructive :foo, :baz
destructive :bar
end
```
or
```ruby
class A
non_destructive
def foo; ... end
def baz; ... end
destructive
def bar; ... end
end
```
When the method is not (yet) specified whether destructive or not, the retu=
rn value can be `"unknown"` (or `:unknown` or `nil`) by default.
```ruby
String.instance_method(:<<).destructive? # =3D> "unknown"
```
--=20
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-c=
ore.ml.ruby-lang.org/