Issue #6308 has been updated by headius (Charles Nutter).


My proposal is that at some time deemed acceptable by ruby-core and Matz, the delegate-based WeakRef should go away, and that in Ruby 2.0 a "preferred" non-delegate WeakRef be added (ideally along with the reference queue support in my other bug).

Here is a patch that adds a non-delegate WeakRef implementation: https://gist.github.com/2516417

This is modeled after the Java WeakRef class, which can only be traversed or cleared. Again, I hope that this would be implemented in an efficient way as part of the GC subsystem, but this implementation should show what I'm looking for. I still whole-heartedly believe that using WeakRef as a delegate is an awful, awful pattern that should be discouraged now and unavailable in the future. This patch would force users to retrieve the weak reference into a hard reference, check it for liveness, and *then* proceed to use the object, which is the only safe way to deal with weak references.
----------------------------------------
Feature #6308: Eliminate delegation from WeakRef
https://bugs.ruby-lang.org/issues/6308#change-26281

Author: headius (Charles Nutter)
Status: Feedback
Priority: Normal
Assignee: 
Category: lib
Target version: 


WeakRef's delegation features are a really awful pattern that should not be allowed in future versions of Ruby.

WeakRef makes no guarantees as to the liveness of its contained object. It can be collected at any time if there are no strong references to it.

WeakRef currently uses delegation to pass method calls through to the contained object. This encourages a pattern where a WeakRef is passed to methods that expect to have a reference to the underlying object, making it appear to be that object.

Unfortunately, this is *never* a good idea. Because the object can be collected at any time, you may get a nil reference from __getobj__ *arbitrarily* in code that tries to call methods against the given WeakRef. That means using WeakRef as a delegate will always result in unreliable code, and errors may happen for inexplicable reasons.

I believe Ruby 2.0 should eliminate WeakRef's delegation features and make it a simple reference holder. There's no safe way to use a weak reference except to grab a reference to the object, check that it is alive (non-nil) and then proceed with the use of the object, as follows:

obj = weakref.__getobj__
raise AppropriateError unless obj
obj.do_something
obj.do_something_else

Along with eliminating delegation, I would recommend simply making the get method #get, since the uglier #__getobj__ is only named that way because it is not delegated.


-- 
http://bugs.ruby-lang.org/