Skip to content

Least and greatest closures are incorrect for contravariant generic typedef #44161

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
iarkh opened this issue Nov 12, 2020 · 1 comment
Closed
Labels
legacy-area-front-end Legacy: Use area-dart-model instead.

Comments

@iarkh
Copy link
Contributor

iarkh commented Nov 12, 2020

Dart SDK version: 2.12.0-29.0.dev (dev) (Mon Nov 9 06:42:00 2020 -0800) on "windows_x64"

Here is a source code example:

Type? _capturedTypeArgument;

X captureTypeArgument<X>() {
  _capturedTypeArgument = X;
  throw "Error";
}

Type? get capturedTypeArgument {
  var result = _capturedTypeArgument;
  _capturedTypeArgument = null;
  return result;
}

typedef F<X> = void Function<Y extends X>();
F<X> toF<X>(X x) => <Y extends X>() {};
Type typeOf<X>() => X;

typedef check<X> = void Function(X x);

void main() {
  void f<X>(check<X> Function() g) => g();
  try { f(() => captureTypeArgument()); } catch(_) {};
  print (typeOf<check>());
  print(capturedTypeArgument);
}

Seems like Never should be substituted as a bound for the check and capturedTypeArgument here, however this is not so and sample output is:

(dynamic) => void
(Never) => void

@eernstg
Copy link
Member

eernstg commented Dec 15, 2020

This is actually working as intended:

print(typeOf<check>()) should print something that means void Function(dynamic), because the meaning of the raw type check is check<dynamic> (using i2b), and that matches the reported printout (dynamic) => void.

print(capturedTypeArgument) should print something that means void Function(Never), which is again a match for (Never) => void. The latter is the greatest closure of void Function(_) with respect to {_} (the set that just contains _), as it should be.

We did have discussions about the initial values for type variables used in the i2b algorithm, and we did consider using the bottom type as the initial value corresponding to a contravariant type parameter, but we ended up using the declared bound with dynamic as the default value.

So I believe we can close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
legacy-area-front-end Legacy: Use area-dart-model instead.
Projects
None yet
Development

No branches or pull requests

3 participants