Skip to content

Inferred type too general? #2069

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
modulovalue opened this issue Jan 14, 2022 · 3 comments
Closed

Inferred type too general? #2069

modulovalue opened this issue Jan 14, 2022 · 3 comments
Labels
least-upper-bound Proposals about improvements of the LUB algorithm

Comments

@modulovalue
Copy link

Hello,

Could it be a bug that the type of listA isn't List<Base<All>> but List<Object>?

My expectation was that the type of listA would be the most specific type possible i.e. List<Base<All>> in this case and not List<Object>.

void main() {
  const listA = [Err(), Leaf()];
  print(listA.runtimeType); // prints List<Object>
  const listB = <Base<All>>[Err(), Leaf()];
  print(listB.runtimeType); // prints List<Base<All>>
}

abstract class Base<H> {}

class Err implements Base<All> {
  const Err();
}

class Leaf implements Base<Valid> {
  const Leaf();
}

abstract class All {}

abstract class Valid implements All {}
@eernstg eernstg added the least-upper-bound Proposals about improvements of the LUB algorithm label Jan 14, 2022
@eernstg
Copy link
Member

eernstg commented Jan 14, 2022

In the case where we're computing the least upper bound of Err and Leaf, the least upper bound algorithm in Dart uses a rule, let's call it Rold, which has been part of the language since Dart 1. In general, Rold is used to find the least upper bound of two class types that aren't generic instantiations of the same class.

The rule Rold is specified here.

This rule is rather simplistic and it yields upper bounds that are considerably less tight than they could be. For example, the least upper bound of Err and Leaf turns out to be Object rather than Base<All>. The basic idea is that it selects the most special shared superinterface of the operands as a whole, and it never applies the least upper bound algorithm on subexpressions of those types. This means that Dart avoids some termination issues that had come up in the context of Java. Moreover, the rule Rold has also been kept unchanged all the time because it is a seriously breaking change to introduce a different rule.

But it is certainly a known issue that the least upper bound algorithm delivers suboptimal results in this particular case. See least-upper-bound Proposals about improvements of the LUB algorithm for more discussions about improving the least upper bounds algorithm.

@modulovalue
Copy link
Author

Note: this issue is relevant to #844 and spebbe/dartz#32. Anyone trying to do something similar will eventually come across this.

@modulovalue
Copy link
Author

I'm going to close this issue because I don't think that it's likely that many people would benefit from focusing on this issue alone.

I think that a fresh discussion around #844 (and, more broadly, use cases for phantom types, e.g., #2865 & #3273) would be needed to make discussing this particular issue worthwhile.

@modulovalue modulovalue closed this as not planned Won't fix, can't repro, duplicate, stale Jan 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
least-upper-bound Proposals about improvements of the LUB algorithm
Projects
None yet
Development

No branches or pull requests

2 participants