mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
32
test/SILGen/dynamic_self_as_lvalue_base.swift
Normal file
32
test/SILGen/dynamic_self_as_lvalue_base.swift
Normal 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 { }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user