Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 29 additions & 19 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -1821,6 +1820,8 @@ namespace {
result, resultTy));
}

closeExistentials(result, locator);

// If we need to load, do so now.
if (loadImmediately) {
result = cs.addImplicitLoadExpr(result);
Expand Down Expand Up @@ -2509,8 +2510,27 @@ namespace {
// Coerce the index argument.
auto openedFullFnType = simplifyType(selected.adjustedOpenedFullType)
->castTo<FunctionType>();

auto openedFullFnTypeSelf = openedFullFnType;

// Now, deal with DynamicSelfType.
if (selected.adjustedOpenedFullType->hasDynamicSelfType()) {
openedFullFnTypeSelf = simplifyType(
selected.adjustedOpenedFullType->eraseDynamicSelfType())
->castTo<FunctionType>();
auto replacementTy = getDynamicSelfReplacementType(
baseTy, subscript, memberLoc);
openedFullFnType = simplifyType(
selected.adjustedOpenedFullType
->replaceDynamicSelfType(replacementTy))
->castTo<FunctionType>();
}

auto fullSubscriptTy = openedFullFnType->getResult()
->castTo<FunctionType>();
auto fullSubscriptTySelf = openedFullFnTypeSelf->getResult()
->castTo<FunctionType>();

auto appliedWrappers =
solution.getAppliedPropertyWrappers(memberLoc->getAnchor());
args = coerceCallArguments(
Expand Down Expand Up @@ -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<FunctionType>()->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;
}

Expand Down
25 changes: 25 additions & 0 deletions test/SILGen/dynamic_self_opened_existential.swift
Original file line number Diff line number Diff line change
@@ -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()
}

18 changes: 18 additions & 0 deletions test/SILGen/dynamic_self_opened_existential_2.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: %target-swift-emit-silgen %s

class AA {
subscript<T>(_: 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
}
}