Bug 440081 - [TypeInference] Mishandling common interface of enums
Summary: [TypeInference] Mishandling common interface of enums
Status: NEW
Alias: None
Product: Xtend
Classification: Tools
Component: Core (show other bugs)
Version: 2.6.0   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-07-22 05:42 EDT by Boris Brodski CLA
Modified: 2016-08-10 10:29 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Boris Brodski CLA 2014-07-22 05:42:28 EDT
Xtend: 2.6.2.v201407030533
Java: 1.7.0_60 (Oracle)


Consider following code snippets:

JAVA:
--------------------------------
public interface MyInterface {}
public enum E1 implements MyInterface{A1, B1}
public enum E2 implements MyInterface{A2, B2}
--------------------------------

XTEND:
--------------------------------
class MyTest {
  def test() {
    val list = #[E1.A1, E2.B2]
    list.forEach [
      val MyInterface i = it
    ]
  }
}
--------------------------------

In the editor the type of list is determined as "List<? extends Enum<?> & MyInterface> list" (hovering tooltip) and no error produces. This type reflects the situation but unfortunately doesn't supported by Java7 (IMHO).

Generated code looks like this:

GENERATED JAVA:
--------------------------------
import com.google.common.collect.Lists;
import java.util.Collections;
import java.util.List;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import test.E1;
import test.E2;
import test.MyInterface;

@SuppressWarnings("all")
public class MyTest {
  public void test() {
    final List<? extends Enum<?>> list = Collections.<Enum<?>>unmodifiableList(Lists.<Enum<?>>newArrayList(E1.A1, E2.B2));
    final Procedure1<MyInterface> _function = new Procedure1<MyInterface>() {
      public void apply(final MyInterface it) {
        final MyInterface i = it;
      }
    };
    IterableExtensions.forEach(list, _function);
  }
}
--------------------------------

and produces the error:


The method forEach(Iterable<T>, Procedures.Procedure1<? super T>) in the type IterableExtensions is not applicable for the arguments (List<capture#1-of ? extends Enum<?>>, Procedures.Procedure1<MyInterface>)
Comment 1 Christian Dietrich CLA 2016-08-10 10:29:22 EDT
as of xtext 2.10 compiles as 


import java.util.Collections;
import java.util.List;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.xtext.example.mydsl1.tests.E1;
import org.xtext.example.mydsl1.tests.E2;
import org.xtext.example.mydsl1.tests.MyInterface;

@SuppressWarnings("all")
public class MyTest {
  public void test() {
    final List<? extends Enum<?>> list = Collections.<Enum<?>>unmodifiableList(CollectionLiterals.<Enum<?>>newArrayList(E1.A1, E2.B2));
    final Procedure1<Enum<?>> _function = new Procedure1<Enum<?>>() {
      @Override
      public void apply(final Enum<?> it) {
        final MyInterface i = ((MyInterface)it);
      }
    };
    IterableExtensions.forEach(list, _function);
  }
}

thus this can no longer be reproduced.

when java 8 is used getting 

public class MyTest {
  public void test() {
    final List<? extends Enum<?>> list = Collections.<Enum<?>>unmodifiableList(CollectionLiterals.<Enum<?>>newArrayList(E1.A1, E2.B2));
    final Consumer<Enum<?>> _function = (Enum<?> it) -> {
      final MyInterface i = ((MyInterface)it);
    };
    list.forEach(_function);
  }
}
Comment 2 Christian Dietrich CLA 2016-08-10 10:29:40 EDT
but this is still not working

class MyTest {
  def test() {
    val list = #[E1.A1, E2.B2]
    val p = [
      val MyInterface i = it
    ]
    list.forEach(p)
  }
}