Skip to content

Ensure analyzer allows desugaring iterable of callable type in for-each to a function type #47471

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
srawlins opened this issue Oct 15, 2021 · 3 comments
Labels
legacy-area-analyzer Use area-devexp instead.

Comments

@srawlins
Copy link
Member

(Analyzer allows this too)

Take this program:

class C {
  void call() {}
}

void foo(Iterable<C> iterable, C c) {
  for (void Function() f in [c /*1*/]) { // This makes sense
    f;
  }

  for (void Function() f in iterable) { // Why is this allowed?
    f;
  }
}

void main() {
  foo([C(), C()], C());
}

The spec says:

Let e be an expression whose static type is an interface
type that has a method named call. In the case where the context type for e
is a function type or the type Function, e is treated as e.call.

I understand why the first is allowed: c /*1*/ has a static type which is an interface type with a call method, and a context type which is a function type.

I don't understand why the second is allowed. In void Function() f in iterable, there is no expression whose static type is an interface type that has a method named call.

Analyzer allows this too but I'm considering it a bug that should be fixed.

@srawlins srawlins added the legacy-area-front-end Legacy: Use area-dart-model instead. label Oct 15, 2021
@eernstg
Copy link
Member

eernstg commented Oct 18, 2021

A for-in statement is specified in terms of desugaring. The .call insertion desugaring is applicable to each element because it is assigned to the iteration variable here.

When the iterable is iterable this works because the static type of the iterable is Iterable<C>. When it is [c] the context type of the iterable would make it <void Function()>[c] such that the .call insertion occurs inside the list literal, in which case there is no need to have another .call insertion in the desugared code. But this still means that both cases should be allowed.

@srawlins
Copy link
Member Author

Thanks @eernstg I will re-word this issue then; the analyzer does not do any desugaring, as far as I know; as I'm rewriting how we do implicit tear-off conversion, I think analayzer's behavior will chang to not allow this conversion in a for-each, which would be a bug.

@srawlins srawlins changed the title CFE allows desugaring iterable of callable type in for-each to a function type Ensure analyzer allows desugaring iterable of callable type in for-each to a function type Oct 18, 2021
@srawlins srawlins added legacy-area-analyzer Use area-devexp instead. and removed legacy-area-front-end Legacy: Use area-dart-model instead. labels Oct 18, 2021
@eernstg
Copy link
Member

eernstg commented Oct 18, 2021

the analyzer does not do any desugaring

That's could very well be the best approach anyway, because an actual desugaring could make it harder to report errors in a way that makes sense in terms of the original source code. So I think it makes sense to look at the desugaring, conclude that certain errors must be reported or certain coercions must be applied to the original code as such, and then apply those checks/coercions to the original source code.

(We could then claim that the whole thing should have been written without the use of syntactic sugar in the first place, but I'm not 100% sure about that either, because a desugaring specification can be a compact and readable way to specify the treatment of certain constructs. We do try to keep desugaring to a minimum in the spec, anyway ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
legacy-area-analyzer Use area-devexp instead.
Projects
None yet
Development

No branches or pull requests

2 participants