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

Intersection type soundness issue #56050

Open
eernstg opened this issue Jun 19, 2024 · 1 comment
Open

Intersection type soundness issue #56050

eernstg opened this issue Jun 19, 2024 · 1 comment
Labels
analyzer-spec Issues with the analyzer's implementation of the language spec area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P2 A bug or feature request we're likely to work on soundness type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@eernstg
Copy link
Member

eernstg commented Jun 19, 2024

Consider the following program:

X id<X extends int>(X x) {
  print(x.isEven); // But `x` is `Object()`!
  return x;
}

void foo<Y>(Y y) {
  if (y is int) { // `y` has type `Y & int`.
    // This invocation is inferred as `id<Y & int>(y)`.
    id(y);
  }
}

void main() => foo<Object>(Object());

This program is accepted with no diagnostics by the analyzer. However, it violates soundness because foo is invoked with an argument of type Object which is passed on to id, and the body of id invokes isEven on that object.

The core reason for this soundness violation is that the invocation id(y) is inferred to have a type argument which is reified as Y, but we cannot prove Y <: int, and this means that the invocation of id is unsound.

It seems likely that this is allowed to happen because type inference of the invocation of id uses the static type of the actual argument, namely Y & int, and this yields an actual type argument that does satisfy the declared bound, as if the invocation had been of the form id<Y & int>(y). This explanation could be wrong, but in that case it is not easy to see why no bound violation error occurs at the invocation of id (or, rather, an error which reports that type inference for id(y) failed).

This is not possible, of course, because Y & int cannot be reified. So it is erased to Y, and that is what is passed as the actual type argument at run time. It is the erasure that introduces the type soundness violation (or, rather, the fact that no checks are performed after the erasure).

The CFE does not have this soundness issue, it correctly reports that inference of an actual type argument to id fails.

@eernstg eernstg added area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. soundness analyzer-spec Issues with the analyzer's implementation of the language spec labels Jun 19, 2024
@eernstg
Copy link
Member Author

eernstg commented Jun 20, 2024

Note this comment, too.

@srawlins srawlins added the type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) label Jun 21, 2024
@scheglov scheglov added the P2 A bug or feature request we're likely to work on label Jun 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
analyzer-spec Issues with the analyzer's implementation of the language spec area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P2 A bug or feature request we're likely to work on soundness type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

3 participants