Skip to content

Conversation

@QuietMisdreavus
Copy link
Contributor

@QuietMisdreavus QuietMisdreavus commented Jun 30, 2025

  • Explanation: USR mangling can include an extension context infix (AAE) when an extended type uses @_originallyDefinedIn on platforms other than the active one. This adds a check for the RespectOriginallyDefinedIn flag when checking extension decls against their extended type.
  • Scope: Changes USR mangling in these situations so that USRs are the same for the same code regardless of platform.
  • Issues: rdar://152598492
  • Original PRs: use RespectOriginallyDefinedIn when mangling extension contexts #82348
  • Risk: Low. The change is limited to situations where the name mangler is already disrespecting the alternate module name, and only additionally turns on that flag for any USR mangling.
  • Testing: Automated tests
  • Reviewers: @edymtt @augusto2112

Resolves rdar://152598492

Consider the following Swift, adapted from a real-world framework:

```swift
@available(macOS 10.8, *)
@_originallyDefinedIn(module: "another", macOS 11.0)
public struct SimpleStruct {}

@available(macOS 12.0, iOS 13.0, *)
public extension SimpleStruct {
    struct InnerStruct {}
}
```

In this scenario, `SimpleStruct` was originally in a module called
`another`, but was migrated to this module around the time of macOS
11.0. Since then, the module was ported to iOS and gained a nested type
`SimpleStruct.InnerStruct`. When mangling USRs for this nested type, the
result differs depending on whether we're targeting macOS or iOS.
They're mostly the same, but the macOS build yields a USR with an `AAE`
infix, designating that the `InnerStruct` was defined in an extension
from a module with the name of the base module. On iOS, this infix does
not exist.

The reason this is happening is because of the implementation of
`getAlternateModuleName` checking the availability spec in the
`@_originallyDefinedIn` attribute against the currently active target.
If the target matches the spec, then the alternate module name is
reported, otherwise the real module name is. Since the iOS build reports
the real module name, the mangling code doesn't bother including the
extension-context infix, instead just opting to include the parent
type's name and moving on.

This PR routes around this issue by passing the
`RespectOriginallyDefinedIn` variable to the
`ExtensionDecl::isInSameDefiningModule` method, and using that to skip
the alternate module name entirely. It also sets
`RespectOriginallyDefinedIn` to `false` in more places when mangling
USRs, but i'm not 100% confident that it was all necessary. The goal was
to make USRs more consistent across platforms, regardless of the
surrounding context.
@QuietMisdreavus QuietMisdreavus requested a review from a team as a code owner June 30, 2025 23:24
@QuietMisdreavus
Copy link
Contributor Author

@swift-ci Please test

@QuietMisdreavus QuietMisdreavus enabled auto-merge (squash) June 30, 2025 23:37
@QuietMisdreavus QuietMisdreavus merged commit a75f94e into release/6.2 Jul 1, 2025
5 checks passed
@QuietMisdreavus QuietMisdreavus deleted the vgm/6.2/alternate-module-usr branch July 1, 2025 07:30
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.

3 participants