Skip to content

Incorrect expectations in co19/LanguageFeatures/Constructor-tear-offs/summary_A01_t01 #1141

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
alexmarkov opened this issue Aug 11, 2021 · 1 comment
Assignees

Comments

@alexmarkov
Copy link

The test verifies that constructor tear-offs have the certain function types:

typedef List<T> Func1<T>(int i, T t);
typedef List<int> Func2(int i1, int i2);
typedef List<List<T>> Func3<T>(int i, T t);
typedef List<List<int>> Func4(int i1, int i2);

const filledList = List.filled; // List<T> Function<T>(int, T)
Expect.isTrue(filledList is Func1);
const filledIntList = List<int>.filled; // List<int> Function(int, int)
Expect.isTrue(filledIntList is Func2);
const filledListList = ListList.filled; // List<List<T>> Function<T>(int, T)
Expect.isTrue(filledListList is Func3);
const filledIntListList = ListList<int>.filled; // List<List<int>> Function(int, int)
Expect.isTrue(filledIntListList is Func4);

There are a couple of problems with these typedefs:

  1. Func1 and Func3 declare generic type aliases to non-generic function types. For example, declaration of Func1 in the new syntax is equivalent to
typedef Func1<T> = List<T> Function(int i, T t);

As a result, is Func1 instantiates type parameter of generic Func1 with default dynamic, and the type check is actually testing is List<dynamic> Function(int i, dynamic t). Constructor tear-off is a generic function, and it doesn't pass type test against non-generic function type.

Instead, Func1 should be declared as a non-generic alias to a generic function type:

typedef Func1 = List<T> Function<T>(int i, T t);
  1. Func3 and Func4 are used to test types of ListList.filled and ListList<int>.filled, where
    typedef ListList<T> = List<List<T>>;

However, they do not properly substitute type parameter E of List to List<T> or List<int> for the 2nd argument (E fill) of List.filled. They use T or int which is not correct.

These type aliases can be corrected in the following way:

typedef Func3 = List<List<T>> Function<T>(int i, List<T> t);
typedef List<List<int>> Func4(int i1, List<int> i2);
@sgrekhov sgrekhov self-assigned this Aug 12, 2021
@sgrekhov
Copy link
Contributor

@alexmarkov thank you for the explanation!

dart-bot pushed a commit to dart-lang/sdk that referenced this issue Aug 12, 2021
…neric classes

When copying types of parameters from a constructor to a signature of
its tear-off, types should be instantiated to substitute class type
parameters with function type parameters.

For example,

  class A<T> {
    A(T x);
  }

  A.new // Should be 'A<S> Function<S>(S x)'

Without instantiation the parameter type would still reference class
type parameter:

  A<S> Function<S>(T x)

As a result, Closure::GetInstantiatedSignature would replace
class type parameters with dynamic (as tear-off doesn't have
instantiated type arguments) which is not correct:

  A<S> Function<S>(dynamic x)

TEST=co19/LanguageFeatures/Constructor-tear-offs/summary_A01_t01
(after dart-lang/co19#1141 is fixed)

Issue #46231

Change-Id: I0517c400271e2a59ab0496a8cc39be51022768b4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/209851
Commit-Queue: Alexander Markov <[email protected]>
Reviewed-by: Tess Strickland <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants