Skip to content

Feature request: Specify unification strategy for generic method types #29780

Closed as not planned
@MichaelRFairhurst

Description

@MichaelRFairhurst

issue #29777 revealed yet another scenario where the lowest-upper-bound unification can work against users intent.

I have talked to @leafpetersen a number of times about better strategies, and the answer seems to be that no single strategy is perfect.

What about a new keyword such as exact, that lets the individual API opt into the constraint unification strategy?

  bool regularEquals<T>(T a, T b);
  bool strictEquals<exact T>(T a, T b);
  ...
  regularEquals("foo", 123); // no type error, unified as regularEquals<Object>()
  strictEquals("foo", 123); // type error
  strictEquals("foo", "bar"); // correct, unified as strictEquals<String>();
  strictEquals<Object>("foo", 123); // correct: "foo" and 123 are both Objects. No unification necessary

I think only one new strategy would be needed (exact). But I could also imagine greatest-lower-bound checks to be useful:

  void runBoth<greatest T>(void firstJob(T input), T secondJob(T input), T val);
  final merged = runBoth((int n) => ..., (num n) => ..., 1); // no type error, infer T as int
  // as opposed to
  void runBothExact<exact T>(void firstJob(T input), T secondJob(T input), T val); 
  final merged = runBothExact((int n) => ..., (num n) => ..., 1); // type error, T is both int and num.

arguably the regular inference rules should be usable with a user-specified upper bound.

  bool nonObjectEquals<T upto Object>(T a, T b);
  nonObjectEquals(1, 1.0); // works, lowest upper bound of "num" chosen
  nonObjectEquals(1, true); // fails, lowest upper bound of "object" violates "upto Object"
  nonObjectEquals<Object>(1, true); // should work? Otherwise this is just `T super Object`.

More likely, I think, there should be one strategy, with a name as simple as exact, but with the semantics of greatest. upto X specifically to me seems presumptuous, though most scenarios that confuse people involving unification are where the inferred type is Object, so maybe a single strategy should be specifyable which has the behavior of upto Object.

Perhaps a better keyword is foo<strict T> so that its meaning can be more flexible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-languageDart language related items (some items might be better tracked at github.com/dart-lang/language).closed-staleClosed as the issue or PR is assumed staletype-enhancementA request for a change that isn't a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions