From bffd46b018dedf711913265a16a789745a35d3a2 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 18 Dec 2025 15:32:35 -0500 Subject: [PATCH] SILGen: Fix assert when emitting re-abstraction thunk in edge case involving opaque return type If we can see the underlying type of an opaque return type, and this underlying type does not depend on the opaque return type's generic signature, then we can end up in a situation where the lowered type of a re-abstraction thunk is not generic, but the formal type is. This would trigger an assertion failure. Check both the lowered type and formal type for type parameters to cope with this. - Fixes https://github.com/swiftlang/swift/issues/86118. --- lib/SIL/IR/SILFunctionType.cpp | 4 +++- test/SILGen/opaque_result_type_thunk.swift | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 test/SILGen/opaque_result_type_thunk.swift diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index 6169d2303bf5c..079ded6fb0097 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -3426,7 +3426,9 @@ CanSILFunctionType swift::buildSILFunctionThunkType( if (!capturedEnvs.empty() || expectedType->hasPrimaryArchetype() || - sourceType->hasPrimaryArchetype()) { + sourceType->hasPrimaryArchetype() || + (inputSubstType && inputSubstType->hasPrimaryArchetype()) || + (outputSubstType && outputSubstType->hasPrimaryArchetype())) { // Get the existing generic signature. baseGenericSig = fn->getLoweredFunctionType() ->getInvocationGenericSignature(); diff --git a/test/SILGen/opaque_result_type_thunk.swift b/test/SILGen/opaque_result_type_thunk.swift new file mode 100644 index 0000000000000..dfacbabb2dd34 --- /dev/null +++ b/test/SILGen/opaque_result_type_thunk.swift @@ -0,0 +1,19 @@ +// RUN: %target-swift-emit-silgen %s + +// https://github.com/swiftlang/swift/issues/86118 + +// The AST type of the thunk depends on the generic signature, but the +// lowered type does not, because we can see the opaque return type's +// underlying type from the expansion point, and it does not involve +// type parameters. Make sure this does not cause us to assert. + +public struct G { + public static func f(_: Any, _: Any) -> some Any { + return 123 + } +} + +public func g(_: T) { + let fn: (Any, Any) -> _ = G.f + let fn2: (Int, Int) -> _ = fn +}