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

Analyzer error message is unclear when a generic function is used as a type argument #34741

Open
iarkh opened this Issue Oct 10, 2018 · 4 comments

Comments

Projects
None yet
5 participants
@iarkh

iarkh commented Oct 10, 2018

Dart SDK Version: 2.1.0-dev.6.0
OS: Windows 10

Analyzer doesn't allow function to use type parameter '<Instance of 'TypeParameterMember'>' as a type argument whereas dart does allow this.

Here is a sample code example:

Type typeOf<X>() => X;

typedef G = Function<X extends num>();
typedef G1<X> = Function();

main() {
  print(typeOf<G>());
  print(typeOf<G1>());
}

Dart passes both with G and G1, sample output is:

() => dynamic
() => dynamic

Analyzer passes with G1 and fails with G. Here is a sample output:

error - Generic function has type parameters '', so it may not be used as a type argument at test.dart:7:16 - generic_function_cannot_be_type_argument
1 error found.

I believe analyzer and dart should behave in the same manner, i.e. both should not (or maybe both should) throw a compile error here.

@eernstg

This comment has been minimized.

Show comment
Hide comment
@eernstg

eernstg Oct 10, 2018

Member

It doesn't make sense to say Generic function has type parameters, because every generic function has that. It might be a bug that the type parameters are ''. ;-)

However, it is true that it is a compile-time error to pass a generic function type as a type argument so generic_function_cannot_be_type_argument is more on track than the full message.

The output from dart doesn't show that G is a generic function type, so I suspect that the front end somehow forgets that, which would be a bug in its own right.

So we have considerations about the analyzer as well as the front end here.

It's inconvenient that we cannot pass any term that denotes a generic function type as a type argument to typeOf, but it shouldn't be a real problem: We can use print(G) and test for G == SomeOtherType etc. to check that G denotes the type that we want it to denote at run time, and that would work for every term T that denotes a generic function type, also when T is not an expression. For instance, consider the situation where we want to check that the dynamic value of F is void Function<X extends num>(Map<String, X>):

typedef F<X extends num> = ... some generic function type that we want to test ...;
typedef F_expected = void Function<Y extends num>(Map<String, Y>);

main() {
  print(F == F_expected);
}

I think it might be helpful to report the issues separately: (1) the front end drops the type argument from the function type (at least when it's printed), and (2) the front end doesn't prevent G from being an actual type argument to typeOf, and (3) the analyzer error message could just say 'A generic function type cannot be a type argument', and the stuff about exactly which type parameters it has is irrelevant.

Member

eernstg commented Oct 10, 2018

It doesn't make sense to say Generic function has type parameters, because every generic function has that. It might be a bug that the type parameters are ''. ;-)

However, it is true that it is a compile-time error to pass a generic function type as a type argument so generic_function_cannot_be_type_argument is more on track than the full message.

The output from dart doesn't show that G is a generic function type, so I suspect that the front end somehow forgets that, which would be a bug in its own right.

So we have considerations about the analyzer as well as the front end here.

It's inconvenient that we cannot pass any term that denotes a generic function type as a type argument to typeOf, but it shouldn't be a real problem: We can use print(G) and test for G == SomeOtherType etc. to check that G denotes the type that we want it to denote at run time, and that would work for every term T that denotes a generic function type, also when T is not an expression. For instance, consider the situation where we want to check that the dynamic value of F is void Function<X extends num>(Map<String, X>):

typedef F<X extends num> = ... some generic function type that we want to test ...;
typedef F_expected = void Function<Y extends num>(Map<String, Y>);

main() {
  print(F == F_expected);
}

I think it might be helpful to report the issues separately: (1) the front end drops the type argument from the function type (at least when it's printed), and (2) the front end doesn't prevent G from being an actual type argument to typeOf, and (3) the analyzer error message could just say 'A generic function type cannot be a type argument', and the stuff about exactly which type parameters it has is irrelevant.

@stereotype441

This comment has been minimized.

Show comment
Hide comment
@stereotype441

stereotype441 Oct 10, 2018

Member

Regarding the last paragraph of @eernstg's comment, agreed. I'm going to file a separate bug for issues (1) and (2), and let this bug represent issue (3).

Member

stereotype441 commented Oct 10, 2018

Regarding the last paragraph of @eernstg's comment, agreed. I'm going to file a separate bug for issues (1) and (2), and let this bug represent issue (3).

@stereotype441

This comment has been minimized.

Show comment
Hide comment
@stereotype441

stereotype441 Oct 10, 2018

Member

Regarding (1), I'm either unable to reproduce this bug, or I'm not understanding it. When I try running this code in the VM:

typedef G = Function<X extends num>();
typedef G1<X> = Function();
main() {
  print(G);
  print(G1);
}

The output I get is:

<X extends num>() => dynamic
() => dynamic

...which I believe is correct. @eernstg, I suspect I'm not understanding what you're getting at. Would you mind filing a separate issue under area-front-end to track the problem you're seeing?

Regarding (2), there is already a bug filed for this: #30931

I'm going to re-title this bug now so that it represents (3) (unclear analyzer error message) and update its labels accordingly.

Member

stereotype441 commented Oct 10, 2018

Regarding (1), I'm either unable to reproduce this bug, or I'm not understanding it. When I try running this code in the VM:

typedef G = Function<X extends num>();
typedef G1<X> = Function();
main() {
  print(G);
  print(G1);
}

The output I get is:

<X extends num>() => dynamic
() => dynamic

...which I believe is correct. @eernstg, I suspect I'm not understanding what you're getting at. Would you mind filing a separate issue under area-front-end to track the problem you're seeing?

Regarding (2), there is already a bug filed for this: #30931

I'm going to re-title this bug now so that it represents (3) (unclear analyzer error message) and update its labels accordingly.

@stereotype441 stereotype441 changed the title from Analyzer doesn't allow function to use type parameter '<Instance of 'TypeParameterMember'>' as a type argument whereas dart does allow this. to Analyzer error message is unclear when a generic function is used as a type argument Oct 10, 2018

@eernstg

This comment has been minimized.

Show comment
Hide comment
@eernstg

eernstg Oct 11, 2018

Member

unable to reproduce this bug

I did not reproduce that behavior here, I just commented on the reported behavior. So, having #30931 for (2) and this one for (3), we're done! ;)

Member

eernstg commented Oct 11, 2018

unable to reproduce this bug

I did not reproduce that behavior here, I just commented on the reported behavior. So, having #30931 for (2) and this one for (3), we're done! ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment