[go: nahoru, domu]

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

analyzer doesn't trust the "is" operator enough #28586

Closed
Hixie opened this issue Feb 1, 2017 · 5 comments
Closed

analyzer doesn't trust the "is" operator enough #28586

Hixie opened this issue Feb 1, 2017 · 5 comments
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). closed-duplicate Closed in favor of an existing report

Comments

@Hixie
Copy link
Contributor
Hixie commented Feb 1, 2017
class A { }

class B { }

class X extends A implements B { }

B test(A o) {
  if (o is B)
    return o; // "The return type 'A' isn't a 'B', as defined by the method 'test'. (test.dart, line 10, col 12)"
  return null;
}

void main() {
  A a = new X();
  print(test(a));
}

This code is correct - on the line with the error, we can prove that o is a B, since it wouldn't get there otherwise.

For now we're working around this with as dynamic on the return line, but that's ugly and loses type checking.

IMHO the analyzer should be able to track that a particular variable is known to implement multiple interfaces at particular points in the code flow.

cc @abarth who just ran into this.

@bwilkerson bwilkerson added the area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). label Feb 1, 2017
@eernstg eernstg added the closed-duplicate Closed in favor of an existing report label Feb 1, 2017
@eernstg
Copy link
Member
eernstg commented Feb 1, 2017

Sect. '16.34 Type Test' in the spec says 'Let v be a local variable or a formal parameter. An is-expression of the form v is T shows that v has type T iff T is more specific than the type S of the expression v and both T != dynamic and S != dynamic'.

So the problem is that A and B are unrelated types, so "promotion" of o to type B wouldn't be a promotion, it would discard the information that o has type A, and then add the information that o has type B.

We could allow for this loss of information (and rename the feature to something like 're-typing' rather than 'type promotion'), or we could introduce intersection types (such that we could know that o is of type A and also of type B, which might be directly denotable as a single type expression such as A & B), but the behavior you see is as currently specified.

We are working on generalizations of the type promotion mechanism, and I listed this issue as one of the subtopics that we'd address when doing that.

With that, I'll close this issue as a duplicate of #18921 (which is not quite true, but that's an old issue which deals with the overall topic of improved promotion, and the list of issues that I created for the language team includes 12 issues in the area, so we won't forget them).

@eernstg eernstg closed this as completed Feb 1, 2017
@eernstg
Copy link
Member
eernstg commented Feb 1, 2017

Oops, forgot to mention this workaround which might be useful—uperform an upcast before promoting:

class A { }
class B { }

class X extends A implements B { }

B test(A o) {
  Object x = o;
  if (x is B)
    return x;
  return null;
}

void main() {
  A a = new X();
  print(test(a));
}

We can only promote variables, not expressions (there's another enhancement to promotion that we are looking at ;-), so we have to introduce the variable x.

@bwilkerson
Copy link
Member

We could allow for this loss of information (and rename the feature to something like 're-typing' rather than 'type promotion') ...

I think the observation is that in this case we really don't care that o is an A inside the if and that what's really being expressed here is equivalent to introducing a local variable named o that hides the o from the outer scope, where the type of the inner variable is B.

The question I would ask is: for all of the is-tests of this form (where the type in the expression is not more specific than the static type of the variable), what percentage of the time is the variable used inside the promotion region as if it also had it's original static type (that is, the variable is treated as if it had an intersection type). Or rather, ask whether it would have been treated that way had it been possible to do so.

@eernstg
Copy link
Member
eernstg commented Feb 1, 2017

Performing 're-typing' rather than 'type promotion' in some cases (and hence getting type B for o in the example) is definitely an interesting design choice; using an intersection type to solve the same problem is another one.

As I mentioned, this issue is linked from the language-team issue about enhanced promotion that I created earlier today, and it says that the linked issues (open as well as closed ones) should be used as sources of information about what's needed, so your comments are included.

@bwilkerson
Copy link
Member

Based on past experience, I'd hesitate to use intersection types if users can't express them syntactically.

But mostly I was suggesting that we could get data to use when making the decision :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). closed-duplicate Closed in favor of an existing report
Projects
None yet
Development

No branches or pull requests

3 participants