Skip to content
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

Variance implementation: Inference fails on tests #43419

Closed
eernstg opened this issue Sep 15, 2020 · 2 comments
Closed

Variance implementation: Inference fails on tests #43419

eernstg opened this issue Sep 15, 2020 · 2 comments
Labels
area-meta Cross-cutting, high-level issues (for tracking many other implementation issues, ...). Epic type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@eernstg
Copy link
Member

eernstg commented Sep 15, 2020

variance_in_inference_test

The test language/variance/variance_in_inference_test fails with the CFE and the analyzer, in several locations.

Inference does not produce the right outcome in at least some of these failure locations:

tests/language/variance/variance_in_inference_test.dart:52:66: Error: The argument type 'Contravariant<Middle>' can't be assigned to the parameter type 'Contravariant<Upper>'.
 - 'Contravariant' is from 'tests/language/variance/variance_in_inference_test.dart'.
 - 'Middle' is from 'tests/language/variance/variance_in_inference_test.dart'.
 - 'Upper' is from 'tests/language/variance/variance_in_inference_test.dart'.
  var inferredMiddle = inferContraContra(Contravariant<Upper>(), Contravariant<Middle>());
                                                                 ^
- Line 52, column 66: COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
  The argument type 'Contravariant<Middle>' can't be assigned to the parameter type 'Contravariant<Upper>'.

The inferred expression is inferContraContra(Contravariant<Upper>(), Contravariant<Middle>()), which allows for T == Middle, but the inference actually chooses Upper, and then there is an error because a Contravariant<Middle> can't be assigned to the resulting parameter type Contravariant<Upper>. The constraints are T <: Upper and T <: Middle, so inference should find the solution T == Middle.

variance_inout_inference_test

Similarly, the test language/variance/variance_inout_inference_test gives rise to an error based on failing inference:

tests/language/variance/variance_inout_inference_test.dart:46:40: Error: The argument type 'Invariant<Middle>' can't be assigned to the parameter type 'Invariant<Upper>'.
 - 'Invariant' is from 'tests/language/variance/variance_inout_inference_test.dart'.
 - 'Middle' is from 'tests/language/variance/variance_inout_inference_test.dart'.
 - 'Upper' is from 'tests/language/variance/variance_inout_inference_test.dart'.
  var inferredMiddle4 = inferInvContra(Invariant<Middle>(), Contravariant<Upper>());
                                       ^
- Line 46, column 40: COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
  The argument type 'Invariant<Middle>' can't be assigned to the parameter type 'Invariant<Upper>'.

variance_in_inference_error_test

A third case with the same issue is language/variance/variance_in_inference_error_test:

variance_in_inference_error_test.dart:32:66: Error: The argument type 'Contravariant<Middle>' can't be assigned to the parameter type 'Contravariant<Upper>'.
 - 'Contravariant' is from 'variance_in_inference_error_test.dart'.
 - 'Middle' is from 'variance_in_inference_error_test.dart'.
 - 'Upper' is from 'variance_in_inference_error_test.dart'.
  var inferredMiddle = inferContraContra(Contravariant<Upper>(), Contravariant<Middle>());
                                                                 ^
error • The argument type 'Contravariant<Middle>' can't be assigned to the parameter type 'Contravariant<Upper>'. • variance_in_inference_error_test.dart:32:66 • argument_type_not_assignable

Again, inference should produce the solution T == Middle from the constraints T <: Upper and T <: Middle, but it chooses T == Upper and then complains. The same issue arises in several other locations in this test.

variance_downwards_inference_test

Finally, the test language/variance/variance_downwards_inference_test reports three spurious errors:

variance_downwards_inference_test.dart:42:25: Error: The argument type 'List<num>' can't be assigned to the parameter type 'List<int>'.
 - 'List' is from 'dart:core'.
  B<int> b = new B(<num>[])..x=2.2;
                        ^
variance_downwards_inference_test.dart:42:32: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
  B<int> b = new B(<num>[])..x=2.2;
                               ^
variance_downwards_inference_test.dart:52:38: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
  D<int> d = new D(3, (num x) {})..x=2.2;
                                     ^
  error • Couldn't infer type parameter 'T'.

Tried to infer 'int' for 'T' which doesn't work:
  Parameter 'x' declared as     'List<T>'
                but argument is 'List<num>'.
The type 'int' was inferred from:
  Return type declared as 'B<T>'
              used where  'B<int>' is required.

Consider passing explicit type argument(s) to the generic.

 • variance_downwards_inference_test.dart:42:18 • could_not_infer
  error • The argument type 'List<num>' can't be assigned to the parameter type 'List<int>'. • variance_downwards_inference_test.dart:42:20 • argument_type_not_assignable
  error • A value of type 'double' can't be assigned to a variable of type 'int'. • variance_downwards_inference_test.dart:42:32 • invalid_assignment
  error • A value of type 'double' can't be assigned to a variable of type 'int'. • variance_downwards_inference_test.dart:52:38 • invalid_assignment

In line 42, the CFE should choose T == num, but it chooses T == int, and the two errors are then implied. T == int is not a solution to the expected constraints, so it seems likely that the generated constraints are not correct. The analyzer chooses int as well, and then detects that it causes errors, and still reports those errors even though they are derived from a choice made during type inference.

In line 52, they should choose T == num, but they actually choose T == int, which causes the reported error. T == int is a solution, but the heuristic for contravariant parameters should choose the most general solution num.

@eernstg eernstg added area-meta Cross-cutting, high-level issues (for tracking many other implementation issues, ...). type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) Epic labels Sep 15, 2020
@eernstg eernstg changed the title Variance implementation: Inference fails on test Variance implementation: Inference fails on tests Sep 15, 2020
@eernstg
Copy link
Member Author

eernstg commented Apr 25, 2023

Refresh as of April 2023: https://dart-ci.firebaseapp.com/current_results/#/filter=language/variance shows that almost every configuration is failing with several tests, including:

  • language/variance/variance_downwards_inference_test
  • language/variance/variance_in_inference_test
  • language/variance/variance_inout_inference_test

copybara-service bot pushed a commit that referenced this issue Nov 9, 2023
After switching over to NNBD, variance inference started failing because
we no longer used variance to subtype match.

This CL adds a null-aware subtype matching fn for the current algorithm.

Bug: #43419
Change-Id: Ifecc58a7537c0656f089cc3f8aca7fd4289be6d2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/334721
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Kallen Tu <kallentu@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
@kallentu
Copy link
Member

Fixed recently with 166f83d.
Thanks for filing this issue Erik!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-meta Cross-cutting, high-level issues (for tracking many other implementation issues, ...). Epic type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

2 participants