Project

General

Profile

Feature #19832

Updated by sawa (Tsuyoshi Sawada) 9 months ago

I propose to add `destructive?` property to `Method` and `UnboundMethod` instances, which shall behave like: 

 ```ruby 
 String.instance_method(:<<).destructive? # => true 
 String.instance_method(:+).destructive? # => false 
 ``` 

 One main purpose of using these classes is to inspect and make sure how a certain method behaves. Besides arity and owner, whether a method is destructive or not is one important piece of information, but currently, you cannot achieve that from `Method` or `UnboundMethod` instances. 

 The problem is how to implement this. It is best if this information (whether 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 ruby level does not call a destructive method anywhere within its own definition, and no dynamic method calls (`send`, `eval`, etc.) are made, then we can 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 internally-called destructive method is applied to a different object). 

 If doing that turns out to be difficult for some or all cases, difficult, then a practical approach for the difficult cases is to label the methods as destructive or not, manually. We can perhaps have methods `Module#destructive` and `Module#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 
 ``` 

 When the method is not (yet) specified whether destructive or not, the return value can be `"unknown"` (or `:unknown` or `nil`) by default. 

 ```ruby 
 String.instance_method(:<<).destructive? # => "unknown" 
 ``` 

Back