Bug 499863 - [1.8][quick assist] Conversion between lambda expression and method reference not semantically equal on instance method
Summary: [1.8][quick assist] Conversion between lambda expression and method reference...
Status: ASSIGNED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.7   Edit
Hardware: PC Windows 10
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: JDT-UI-Inbox CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
: 520434 (view as bug list)
Depends on: 353759
Blocks: 449106
  Show dependency tree
 
Reported: 2016-08-17 16:51 EDT by Viliam Anirud CLA
Modified: 2022-10-08 19:25 EDT (History)
6 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Viliam Anirud CLA 2016-08-17 16:51:46 EDT
When converting lambda expression to method reference or vice versa and when the method is an instance method, the instance scope is not taken into account.

   myInstance::myMethod

is converted to

   () -> myInstance.myMethod()

However, in the former case, myInstance is evaluated at the lambda creation time while in the later case it is evaluated when the lambda is executed. These two are not semantically equivalent. The above conversion is only safe, if myInstance is final. The lambda expression should be:

   MyInstanceClass myInstanceCopy = myInstance;
   () -> myInstanceCopy.myMethod()

Here is a more complete example:


  import java.util.function.Supplier;
  
  public class Test {
  
    static class Clazz {
      private final String value;
      
      public Clazz(String value) {
        this.value = value;
      }
      
      public String getValue() {
        return value;
      }
    }
    
    static Clazz myInstance;
    
    public static void main(String[] args) {
      myInstance = new Clazz("a");
      
      Supplier<String> supplierMethodRef = myInstance::getValue;
      // The following lambda expression is the result of conversion
      // of the method reference on the previous line to lambda
      Supplier<String> supplierLambda = () -> myInstance.getValue();
  
      System.out.println(supplierLambda.get());
      System.out.println(supplierMethodRef.get());
      
      // after changing the value of "x", the result is different in each case
      myInstance = new Clazz("b");
      System.out.println(supplierLambda.get());
      System.out.println(supplierMethodRef.get());
    }
  }



As far as I know, there is not a way to express a lambda as a method reference in equivalent way, if the instance is not final. The current implementation is confusing, as people believe that refactored code is equivalent.
Comment 1 Stephan Herrmann CLA 2016-08-17 17:03:48 EDT
When the receiver is a local variable, the language rules already enforce that it be effectively final. Such a rule does not exist for fields, so, yes, in this case the point in time when the receiver value is captured is relevant, and the refactoring invisibly changes this.
Comment 2 Markus Keller CLA 2016-12-21 12:19:29 EST
Although the Quick Assist is not completely semantically preserving, it may still be useful depending on the circumstances.

I don't think we should disable the Quick Assist in this case, but we should mark it as potentially dangerous with the facility from bug 353759 (which is not implemented yet).
Comment 3 Noopur Gupta CLA 2017-08-02 09:44:17 EDT
*** Bug 520434 has been marked as a duplicate of this bug. ***
Comment 4 Eclipse Genie CLA 2020-09-08 12:21:08 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.
Comment 5 Eclipse Genie CLA 2022-10-08 19:25:05 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.