diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 167f25c810899..47d2f97fb10f6 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); @@ -2509,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( @@ -2564,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 new file mode 100644 index 0000000000000..a5ec8128197ea --- /dev/null +++ b/test/SILGen/dynamic_self_opened_existential.swift @@ -0,0 +1,25 @@ +// 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() + + 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 + } +}