SILGen: Limit references to NSError in inlinable code optimization

Revisit the optimization that provides a fast path for instances of
`NSError` when erasing the `Error` type in `emitExistentialErasure`. It
generated references to `NSError` when the `Foundation` module was
loaded, no matter how it was imported. This lead to deserialization
failures at reading the swiftmodule when that reference was added to
inlinable code while `Foundation` was not a public dependency.

Fix this crash by limiting the optimization to all non-inlinable code
and only inlinable code from a module with a public dependency on
`Foundation`. This is the similar check we apply to user written
inlinable code, however here we use the module-wide dependency instead
of per file imports.

rdar://142438679
This commit is contained in:
Alexis Laferrière
2025-02-18 16:44:28 -08:00
parent a619daf12b
commit db7126c390
4 changed files with 200 additions and 1 deletions

View File

@@ -656,9 +656,10 @@ ManagedValue SILGenFunction::emitExistentialErasure(
// If we're erasing to the 'Error' type, we might be able to get an NSError
// representation more efficiently.
auto &ctx = getASTContext();
auto *nsErrorDecl = ctx.getNSErrorDecl();
if (ctx.LangOpts.EnableObjCInterop && conformances.size() == 1 &&
conformances[0].getRequirement() == ctx.getErrorDecl() &&
ctx.getNSErrorDecl()) {
nsErrorDecl && referenceAllowed(nsErrorDecl)) {
// If the concrete type is NSError or a subclass thereof, just erase it
// directly.
auto nsErrorType = ctx.getNSErrorType()->getCanonicalType();