From 782d68fc99ea91ccb44783e4a8836f079d1ec0c8 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 30 Sep 2025 12:46:03 -0400 Subject: [PATCH 1/2] Sema: Fix malformed AST when both DynamicSelfType and opened existentials are involved This worked for functions, but for properties, we did things in the wrong order. Fixes rdar://160816868. --- lib/Sema/CSApply.cpp | 3 ++- .../dynamic_self_opened_existential.swift | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 test/SILGen/dynamic_self_opened_existential.swift diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 167f25c810899..b52a7c29623ae 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -1809,7 +1809,6 @@ namespace { result = adjustTypeForDeclReference(result, resultTySelf, resultType(adjustedRefTySelf), locator); - closeExistentials(result, locator); // If the property is of dynamic 'Self' type, wrap an implicit // conversion around the resulting expression, with the destination @@ -1821,6 +1820,8 @@ namespace { result, resultTy)); } + closeExistentials(result, locator); + // If we need to load, do so now. if (loadImmediately) { result = cs.addImplicitLoadExpr(result); diff --git a/test/SILGen/dynamic_self_opened_existential.swift b/test/SILGen/dynamic_self_opened_existential.swift new file mode 100644 index 0000000000000..7092373975e9d --- /dev/null +++ b/test/SILGen/dynamic_self_opened_existential.swift @@ -0,0 +1,26 @@ +// RUN: %target-swift-emit-silgen %s + +public class C { + public func f() -> Self { return self } + public var v: Self { return self } + public subscript() -> Self { return self } + + public func g1() {} +} + +public protocol P { + func g2() +} + +func f(_ p: any P & C) { + p.f().g1() + p.f().g2() + + p.v.g1() + p.v.g2() + + // FIXME + // p[].g1() + // p[].g2() +} + From 5be227a9b96dd87973e74387befc7d4f6dc2ed81 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 30 Sep 2025 13:41:38 -0400 Subject: [PATCH 2/2] Sema: Fix the same bug with subscripts as well Fixes rdar://161588385. --- lib/Sema/CSApply.cpp | 45 +++++++++++-------- .../dynamic_self_opened_existential.swift | 5 +-- .../dynamic_self_opened_existential_2.swift | 18 ++++++++ 3 files changed, 47 insertions(+), 21 deletions(-) create mode 100644 test/SILGen/dynamic_self_opened_existential_2.swift diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index b52a7c29623ae..47d2f97fb10f6 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -2510,8 +2510,27 @@ namespace { // Coerce the index argument. auto openedFullFnType = simplifyType(selected.adjustedOpenedFullType) ->castTo(); + + auto openedFullFnTypeSelf = openedFullFnType; + + // Now, deal with DynamicSelfType. + if (selected.adjustedOpenedFullType->hasDynamicSelfType()) { + openedFullFnTypeSelf = simplifyType( + selected.adjustedOpenedFullType->eraseDynamicSelfType()) + ->castTo(); + auto replacementTy = getDynamicSelfReplacementType( + baseTy, subscript, memberLoc); + openedFullFnType = simplifyType( + selected.adjustedOpenedFullType + ->replaceDynamicSelfType(replacementTy)) + ->castTo(); + } + auto fullSubscriptTy = openedFullFnType->getResult() ->castTo(); + auto fullSubscriptTySelf = openedFullFnTypeSelf->getResult() + ->castTo(); + auto appliedWrappers = solution.getAppliedPropertyWrappers(memberLoc->getAnchor()); args = coerceCallArguments( @@ -2565,38 +2584,28 @@ namespace { if (!base) return nullptr; - bool hasDynamicSelf = fullSubscriptTy->hasDynamicSelfType(); - // Form the subscript expression. auto subscriptExpr = SubscriptExpr::create( ctx, base, args, subscriptRef, isImplicit, semantics); subscriptExpr->setIsSuper(isSuper); - if (!hasDynamicSelf) { - cs.setType(subscriptExpr, fullSubscriptTy->getResult()); - } else { - cs.setType(subscriptExpr, - fullSubscriptTy->getResult() - ->replaceDynamicSelfType(containerTy)); - } + cs.setType(subscriptExpr, fullSubscriptTySelf->getResult()); Expr *result = subscriptExpr; - closeExistentials(result, locator); // If the element is of dynamic 'Self' type, wrap an implicit conversion // around the resulting expression, with the destination type having // 'Self' swapped for the appropriate replacement type -- usually the // base object type. - if (hasDynamicSelf) { - const auto conversionTy = simplifyType( - selected.adjustedOpenedType->castTo()->getResult()); - - if (!containerTy->isEqual(conversionTy)) { - result = cs.cacheType( - new (ctx) CovariantReturnConversionExpr(result, conversionTy)); - } + if (!fullSubscriptTy->getResult()->isEqual( + fullSubscriptTySelf->getResult())) { + result = cs.cacheType( + new (ctx) CovariantReturnConversionExpr( + result, fullSubscriptTy->getResult())); } + closeExistentials(result, locator); + return result; } diff --git a/test/SILGen/dynamic_self_opened_existential.swift b/test/SILGen/dynamic_self_opened_existential.swift index 7092373975e9d..a5ec8128197ea 100644 --- a/test/SILGen/dynamic_self_opened_existential.swift +++ b/test/SILGen/dynamic_self_opened_existential.swift @@ -19,8 +19,7 @@ func f(_ p: any P & C) { p.v.g1() p.v.g2() - // FIXME - // p[].g1() - // p[].g2() + p[].g1() + p[].g2() } diff --git a/test/SILGen/dynamic_self_opened_existential_2.swift b/test/SILGen/dynamic_self_opened_existential_2.swift new file mode 100644 index 0000000000000..de330bc8f7966 --- /dev/null +++ b/test/SILGen/dynamic_self_opened_existential_2.swift @@ -0,0 +1,18 @@ +// RUN: %target-swift-emit-silgen %s + +class AA { + subscript(_: T.Type) -> T? { + get { fatalError() } + set {} + } +} + +class C { + typealias A = AA + + func f() { + let a = AA() + guard let result = a[Self.A.self] else { return } + _ = result + } +}