eclipse-archived / ceylon

The Ceylon compiler, language module, and command line tools
http://ceylon-lang.org
Apache License 2.0
395 stars 62 forks source link

Backend error when method reference passed to method triggering SAM-interface interop #7379

Open kingjon3377 opened 6 years ago

kingjon3377 commented 6 years ago

The following code fails to compile with a backend error:

import javax.swing {
    JComponent,
    JButton
}
import java.awt.event {
    ActionEvent
}
Anything(ActionEvent) silentListener(Anything() listener) =>
        void (ActionEvent event) => listener();
void consumer(Anything(ActionEvent) val) {}
class Sample() extends JComponent() {
    value memberVariable = JButton();
    consumer(silentListener(memberVariable.updateUI)); // works
    value listener = silentListener(memberVariable.updateUI); // works
    memberVariable.addActionListener(listener); // works
    // Ceylon backend error: variable $instance$ is already defined in constructor Sample()
    memberVariable.addActionListener(silentListener(memberVariable.updateUI));
}

The backend error does not occur if the return value of the transforming method (silentListener in the code above) is assigned to a variable, even if that variable is used in a way that the compiler transforms to a Java SAM interface, nor if it is passed to a method expecting a Ceylon Callable.

I've reproduced this both on the command line (ceylon --version reports ceylon version 1.3.3 0d594b3 (Contents May Differ); I'm on Mac OS X Sierra, with the Ceylon distribution installed via Homebrew) and in the Eclipse IDE (AFAICT the latest version, which the "About Eclipse Features" reports as version 1.3.3v20170818-1632-Final, running on Eclipse 4.7.3a).

gavinking commented 5 years ago

Related issue #7380.

kingjon3377 commented 5 years ago

It looks like this may not be (entirely) specific to the SAM-interface interop; I ran into the same error with code that I distilled to the following:

void callee(String?() arg) {}
void caller(Resource resource) =>
    callee(LinkedList(resource.textContent().split('\n'.equals)).accept);

The compiler output puts the "error here" caret underneath the first character of '\n'.equals.