jsweet icon indicating copy to clipboard operation
jsweet copied to clipboard

Iterable interface cannot be extended

Open vorth opened this issue 2 years ago • 4 comments

This is a regression, as it was working in 2.3.7.

I suspect the default methods in Iterable are the issue, but it is just a guess.

Paste this code into the live sandbox to demonstrate the spurious compile error:

package org.jsweet;

import static def.dom.Globals.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

public class HelloWorld {
	public static void main(String[] args) {
		WrappedList list = new WrappedListImpl();  // WrappedList interface inherits the iterable method, and yet...
		for( int num : list ) { // TSC fails with "property 'iterator' does not exist on type 'WrappedList'"
			System.out.println( num );
		}
	}
}

public interface WrappedList extends Iterable<Integer> {
	
	public void doSomething();
}

public class WrappedListImpl implements WrappedList {
	
	private List<Integer> nums = new ArrayList<>();
		
	public WrappedListImpl() {
		this.nums.add( 3 );
		this.nums.add( 5 );
		this.nums.add( 8 );
	}
	
        public Iterator<Integer> iterator() {
		return this.nums.iterator();
	}
	
	public void doSomething() {
	}
}

vorth avatar Aug 21 '22 01:08 vorth

It seems that the extends Iterable<Integer> gets erased by design:

https://github.com/cincheo/jsweet/blob/ac8ef70abdd7665bb61fa82af53c09baa9c789f5/transpiler/src/main/java/org/jsweet/transpiler/Java2TypeScriptTranslator.java#L1722

I don't understand why this is designed in this way. Can someone explain? If the interface extension is erased, shouldn't its methods be inlined?

vorth avatar Sep 03 '22 00:09 vorth

Standard JSweet behavior (without j4ts) is to remove java references and replace it with a JS implementation. Since Iterable is not a JS type, it won't appear at runtime.

What you see in the code you linked above is a call to an adapter, which allows to switch behavior when necessary, for instance if you need to keep some type in a specific project. By default, the RemoveJavaDependenciesAdapter is used, but any implementation can be used.

Is it a problem that this super interface gets erased in TypeScript? I honestly doubt this is related to this issue?

lgrignon avatar Sep 03 '22 12:09 lgrignon

I believe the error comes from the TypeScript compiler:

Line 11: property 'iterator' does not exist on type 'WrappedList'

If you look at the generated TypeScript, you can see that the problem is a TS source issue with the missing iterator() method.

I'll take a look at RemoveJavaDependenciesAdapter. It seems wrong to remove superinterfaces without inlining them, in general. I suspect many of my JSweet transpile errors are a result of this.

vorth avatar Sep 03 '22 17:09 vorth

Yes, methods are supposed to be inlined indeed. This sounds like a bug.

You will find somewhere in the translator some code to handle inlining of default methods specifically.

lgrignon avatar Sep 03 '22 17:09 lgrignon