Skip to content

[6.0] Devirtualizer: fix a crash due to a not supported bitcast of ABI compatible types #74653

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

Merged
merged 2 commits into from
Jun 24, 2024

Conversation

eeckstein
Copy link
Contributor

  • Explanation: Fixes a compiler crash in the de-virtualizer pass.
    When devirtualizing witness method calls, it can happen that we need a cast between ABI compatible return types.
    We were missing supporting type casts between nominal types which are ABI compatible.

This comes from whole-module reasoning of protocol conformances.
If a protocol only has a single conformance where the associated type (ID) is some concrete type (e.g. Int), then the devirtualizer knows that p.get() can only return an Int:

public struct X2<ID> {
  let p: any P2<ID>
  public func testit(i: ID, x: ID) -> S2<ID> {
    return p.get(x: x)
  }
}

and after devirtualizing the get function, its result must be cast from Int to ID.

…ut is dependent on its generic parameters

This is usually the case. Some examples, where they layout is _not_ dependent:
```
   struct S<T> {
     var x: Int // no members which depend on T
   }

   struct S<T> {
     var c: SomeClass<T> // a class reference does not depend on the layout of the class
   }
```
…atible types

When devirtualizing witness method calls, it can happen that we need a cast between ABI compatible return types.
We were missing supporting type casts between nominal types which are ABI compatible.

This comes from whole-module reasoning of protocol conformances.
If a protocol only has a single conformance where the associated type (`ID`) is some concrete type (e.g. `Int`), then the devirtualizer knows that `p.get()` can only return an `Int`:
```
public struct X2<ID> {
  let p: any P2<ID>
  public func testit(i: ID, x: ID) -> S2<ID> {
    return p.get(x: x)
  }
}
```
and after devirtualizing the `get` function, its result must be cast from `Int` to `ID`.

The `layoutIsTypeDependent` utility is basically only used here to assert that this cast can only happen between layout compatible types.

rdar://129004015
@eeckstein eeckstein requested a review from a team as a code owner June 24, 2024 07:56
@eeckstein eeckstein requested a review from slavapestov June 24, 2024 07:56
@eeckstein
Copy link
Contributor Author

@swift-ci test

@eeckstein eeckstein merged commit a823cad into swiftlang:release/6.0 Jun 24, 2024
5 checks passed
@eeckstein eeckstein deleted the fix-devirtualizer-6.0 branch June 24, 2024 17:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants