Generic Constraint doesn't resolve correctly in Nested types

I get an error “Generic parameter doesn't fulfill constraint” if the generic type is also a nested type.

For example, given this generic interface:

type
  BasePresenter = public interface
  end;
  
  BaseView<T> = public interface
	where T is BasePresenter;
  end;

This does not compile:

type
  ListContract = public interface
  end;
  
  Presenter nested in ListContract = public interface(BasePresenter)
  end;
  
  View nested in ListContract = public interface(BaseView<Presenter>)
  end;

But this does:

type
  ListContract = public interface
  end;
  
  FakePresenter = public interface(BasePresenter)
  end;
  
  View nested in ListContract = public interface(BaseView<FakePresenter>)
  end;

I get an error “Generic parameter doesn't fulfill constraint” on ListContract.View. The only change is that the working version provides a non-nested descendant of BasePresenter as the generic type while the failing version provides the nested interface ListContract.Presenter.

Which version of Element are you using? I am using the latest Element Build 2480, and everything compiled just as expected.

I don’t see " Generic parameter doesn't fulfill constrain error.

Also what platform (I assume Java?)? Can I get a full project?

Odd. I’m on 2479.

Yeah, it’s in my Android app. I do have delphi legacy enabled, so perhaps that’s affecting something?

Sure, I’ll send one

Hmm it’s compiling for me on a clean project. I’ll play around with the settings to see what reproduces the issue.

1 Like

Ok I was able to reproduce it. It is just a really bizarre case of inaccurate error reporting. To reproduce the case, I had to provide a concrete implementation of the interface and change a return type to match technically but not exactly.

So given this interface:

  Presenter nested in ListContract = public interface(BasePresenter)
    method getData: ArrayList<String>;
  end;

This implementation will not compile:

interface
  uses
    java.util;

  type
    PresenterImpl = public interface(ListContract.Presenter)
      method getData: ArrayList<String>;
    end;

implementation

method PresenterImpl.getData: java.util.ArrayList<String>;
begin
end;

Because the implementation is java.util.ArayList instead of just ArrayList. This is the code in my example project below. Simply changing java.util.ArrayList to ArrayList allows it to compile.

For some reason the error ends up being “Generic parameter doesn't fulfill constraint "BasePresenter" for "T"” on ListContract.View :man_shrugging:

ConstrainedGenerics.zip (97.8 KB)

I should note, this was the cause in my main project as well. I was referencing android.text.SpannableString instead of SpannableString in a return type.