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

Type inference #739

Closed
a-eid opened this issue Dec 13, 2019 · 1 comment
Closed

Type inference #739

a-eid opened this issue Dec 13, 2019 · 1 comment
Labels
feature Proposed language feature that solves one or more problems

Comments

@a-eid
Copy link

a-eid commented Dec 13, 2019

if dart can infer the type of padding then

  padding: EdgeInsets.all(16.0),

ideally would be

  padding: .all(16.0),

I know this feature exists in swift but I'm not so sure what it's called.

@a-eid a-eid added the feature Proposed language feature that solves one or more problems label Dec 13, 2019
@eernstg
Copy link
Member

eernstg commented Dec 13, 2019

That's actually an instance creation where we have a named constructor (with name EdgeInsets.all) and we specify only the latter half of the name in the instance creation (.all, plus the normal argument list).

Assuming that the syntax doesn't create nasty ambiguities, it would certainly be possible to allow constructs like .all(16.0), and then use the context type P to find a set of candidate constructors (such that the type of the resulting instance creation, e.g., EdgeInsets.all(16.0), would have the required type). However, it could be a rather brittle mechanism:

class A { A.name(); }
class B1 implements A { B1.name(); }
class B2 implements A { B2.name(); }

main() {
  A x = .name(); // Complete to `A.name()`, `B1.name()`, or `B2.name()`?
}

There could be many classes with a named constructor matching .name(), so we would need to have a robust disambiguation mechanism.

If we directly use the context type A (and ignore all subtypes like B1 and B2) then it might be easy to disambiguate, but if the developer used to have B1 x = .name() and then wanted to clean up the code (because nobody uses the interface of B1, it's all declared in A anyway), then a seemingly benign little cleanup will actually change the class of the new instance, which may well be a bug.

Also, with var x = .name() we would require a search over all classes in scope, collecting each class C that has a constructor named C.name, and selecting one of them. To me that sounds error prone.

One possible variant of this mechanism could be a local import (#267). This requires a local import directive, but that might be an OK overhead if a name like EdgeInsets would otherwise be used many times:

main() {
  import EdgeInsets; // Maybe EdgeInsets, Colors, AndMore.
  Lots(Of(Stuff(...
    padding: all(16.0), // `all` is now in scope, meaning `EdgeInsets.all`.
  )));
}

With a local import like this, we'd resolve the missing name using the normal scope rules, and the identifier EdgeInsets occurs explicitly in the enclosing code, such that the meaning of the code won't silently change just because someone made a little adjustment to the type annotation on the parameter named padding.

@a-eid a-eid closed this as completed Jan 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

2 participants