Sema: Don't stick CovariantReturnConversionExpr around property access with DynamicSelfType base

It could be that refTy->hasDynamicSelfType() is true whereas
varDecl->getValueInterfaceType()->hasDynamicSelfType() is false.
This happens if the base of the access is dynamic Self, so the
refTy is (Self) -> @lvalue Int or whatever.

Note that replaceDynamicSelfType() behaves correctly in this case;
it leaves that Self in place, because it's in contravariant
position.

However, the other place where we check the condition would then
form a nonsensical CovariantReturnConversionExpr around the result
of the access, even though no conversion was necessary here; the
type of the returned value does not involve Self.

Simplify this logic further with the correct condition.

Fixes rdar://159531634.
This commit is contained in:
Slava Pestov
2025-09-06 16:26:01 -04:00
parent e5f9ffce12
commit ab4e754ef9
2 changed files with 38 additions and 7 deletions

View File

@@ -1789,23 +1789,23 @@ namespace {
base->setImplicit();
}
const auto hasDynamicSelf = refTy->hasDynamicSelfType();
auto memberRefExpr
= new (ctx) MemberRefExpr(base, dotLoc, memberRef,
memberLoc, Implicit, semantics);
memberRefExpr->setIsSuper(isSuper);
auto resultTy = resultType(refTy);
bool hasDynamicSelf = resultTy->hasDynamicSelfType();
if (hasDynamicSelf) {
refTy = refTy->replaceDynamicSelfType(containerTy);
adjustedRefTy = adjustedRefTy->replaceDynamicSelfType(
containerTy);
}
cs.setType(memberRefExpr, resultType(refTy));
cs.setType(memberRefExpr, resultTy);
Expr *result = memberRefExpr;
result = adjustTypeForDeclReference(result, resultType(refTy),
result = adjustTypeForDeclReference(result, resultTy,
resultType(adjustedRefTy),
locator);
closeExistentials(result, locator);
@@ -1815,10 +1815,9 @@ namespace {
// type having 'Self' swapped for the appropriate replacement
// type -- usually the base object type.
if (hasDynamicSelf) {
const auto conversionTy = adjustedOpenedType;
if (!containerTy->isEqual(conversionTy)) {
if (!resultTy->isEqual(adjustedOpenedType)) {
result = cs.cacheType(new (ctx) CovariantReturnConversionExpr(
result, conversionTy));
result, adjustedOpenedType));
}
}

View File

@@ -0,0 +1,32 @@
// RUN: %target-swift-emit-silgen %s
class C: P1, P2 {
public func f(_ n: Int) -> Self {
self.x = n
self.y = n
self.z = n
return self
}
public var x: Int? {
get { fatalError() }
set { }
}
}
protocol P1: AnyObject {}
protocol P2 {}
extension P1 {
public var y: Int? {
get { fatalError() }
set { }
}
}
extension P2 {
public var z: Int? {
get { fatalError() }
nonmutating set { }
}
}